///////////////////////////////////////////////////////////////////////////// // Name: src/qt/font.cpp // Author: Peter Most, Mariano Reingart, Javier Torres // Copyright: (c) 2009 wxWidgets dev team // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #include #include #include "wx/font.h" #include "wx/fontutil.h" #include "wx/qt/private/utils.h" #include "wx/qt/private/converter.h" // Older versions of QT don't define all the QFont::Weight enum values, so just // do it ourselves here for all case instead. #if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)) #define wxQFontEnumOrInt(a, b) a #else #define wxQFontEnumOrInt(a, b) b #endif enum { wxQFont_Thin = wxQFontEnumOrInt( QFont::Thin, 0 ), wxQFont_ExtraLight = wxQFontEnumOrInt( QFont::ExtraLight, 12 ), wxQFont_Light = QFont::Light, wxQFont_Normal = QFont::Normal, wxQFont_Medium = wxQFontEnumOrInt( QFont::Medium, 57 ), wxQFont_DemiBold = QFont::DemiBold, wxQFont_Bold = QFont::Bold, wxQFont_ExtraBold = wxQFontEnumOrInt( QFont::ExtraBold, 81 ), wxQFont_Black = QFont::Black }; static QFont::StyleHint ConvertFontFamily(wxFontFamily family) { switch (family) { case wxFONTFAMILY_DEFAULT: return QFont::AnyStyle; case wxFONTFAMILY_DECORATIVE: return QFont::Decorative; case wxFONTFAMILY_ROMAN: return QFont::Serif; case wxFONTFAMILY_SCRIPT: return QFont::Decorative; case wxFONTFAMILY_SWISS: return QFont::SansSerif; case wxFONTFAMILY_MODERN: return QFont::TypeWriter; case wxFONTFAMILY_TELETYPE: return QFont::TypeWriter; case wxFONTFAMILY_MAX: wxFAIL_MSG( "Invalid font family value" ); break; } return QFont::AnyStyle; } // Helper of ConvertFontWeight() and GetNumericWeight(): if a value lies in // ]fromMin, fromMax] interval, then map it to [toMin, toMax] interval linearly // and return true, otherwise return false and don't modify it. static bool TryToMap(int& x, int fromMin, int fromMax, int toMin, int toMax) { if ( x > fromMin && x <= fromMax ) { x = (toMin*(fromMax - x) + toMax*(x - fromMin))/(fromMax - fromMin); return true; } return false; } static int ConvertFontWeight(int w) { // Note that wxQFont_Thin is 0, so we can't have anything lighter than it. if ( TryToMap(w, wxFONTWEIGHT_INVALID, wxFONTWEIGHT_THIN, wxQFont_Thin, wxQFont_Thin) || TryToMap(w, wxFONTWEIGHT_THIN, wxFONTWEIGHT_EXTRALIGHT, wxQFont_Thin, wxQFont_ExtraLight) || TryToMap(w, wxFONTWEIGHT_EXTRALIGHT, wxFONTWEIGHT_LIGHT, wxQFont_ExtraLight, wxQFont_Light) || TryToMap(w, wxFONTWEIGHT_LIGHT, wxFONTWEIGHT_NORMAL, wxQFont_Light, wxQFont_Normal) || TryToMap(w, wxFONTWEIGHT_NORMAL, wxFONTWEIGHT_MEDIUM, wxQFont_Normal, wxQFont_Medium) || TryToMap(w, wxFONTWEIGHT_MEDIUM, wxFONTWEIGHT_SEMIBOLD, wxQFont_Medium, wxQFont_DemiBold) || TryToMap(w, wxFONTWEIGHT_SEMIBOLD, wxFONTWEIGHT_BOLD, wxQFont_DemiBold, wxQFont_Bold) || TryToMap(w, wxFONTWEIGHT_BOLD, wxFONTWEIGHT_EXTRABOLD, wxQFont_Bold, wxQFont_ExtraBold) || TryToMap(w, wxFONTWEIGHT_EXTRABOLD, wxFONTWEIGHT_HEAVY, wxQFont_ExtraBold, wxQFont_Black) || TryToMap(w, wxFONTWEIGHT_HEAVY, wxFONTWEIGHT_EXTRAHEAVY, wxQFont_Black, 99) ) { return w; } wxFAIL_MSG("invalid wxFont weight"); return wxQFont_Normal; } class wxFontRefData: public wxGDIRefData { public: wxFontRefData() {} wxFontRefData(const wxFontInfo& info) { if ( info.HasFaceName() ) m_nativeFontInfo.SetFaceName(info.GetFaceName()); else m_nativeFontInfo.SetFamily(info.GetFamily()); if ( info.IsUsingSizeInPixels() ) m_nativeFontInfo.SetPixelSize(info.GetPixelSize()); else m_nativeFontInfo.SetFractionalPointSize(info.GetFractionalPointSize()); m_nativeFontInfo.SetStyle(info.GetStyle()); m_nativeFontInfo.SetWeight(info.GetWeight()); m_nativeFontInfo.SetUnderlined(info.IsUnderlined()); m_nativeFontInfo.SetStrikethrough(info.IsStrikethrough()); } wxFontRefData( const wxFontRefData& data ) : wxGDIRefData() { m_nativeFontInfo.m_qtFont = data.m_nativeFontInfo.m_qtFont; } wxNativeFontInfo m_nativeFontInfo; }; #define M_FONTDATA ((wxFontRefData *)m_refData)->m_nativeFontInfo wxFont::wxFont() { m_refData = new wxFontRefData(); } wxFont::wxFont(const wxFontInfo& info) { m_refData = new wxFontRefData(info); } wxFont::wxFont(const wxString& nativeFontInfoString) { m_refData = new wxFontRefData(); QFont font; font.fromString(wxQtConvertString( nativeFontInfoString )); M_FONTDATA.m_qtFont = font; } wxFont::wxFont(const wxNativeFontInfo& info) { m_refData = new wxFontRefData(); M_FONTDATA.m_qtFont = info.m_qtFont; } wxFont::wxFont(const QFont& font) { m_refData = new wxFontRefData(); M_FONTDATA.m_qtFont = font; } wxFont::wxFont(int size, wxFontFamily family, wxFontStyle style, wxFontWeight weight, bool underlined, const wxString& face, wxFontEncoding encoding) { m_refData = new wxFontRefData(); Create(wxSize(0, size), family, style, weight, underlined, face, encoding); } wxFont::wxFont(const wxSize& pixelSize, wxFontFamily family, wxFontStyle style, wxFontWeight weight, bool underlined, const wxString& face, wxFontEncoding encoding) { Create(pixelSize, family, style, weight, underlined, face, encoding); } wxFont::wxFont(int size, int family, int style, int weight, bool underlined, const wxString& face, wxFontEncoding encoding) { Create(wxSize(0, size), (wxFontFamily)family, (wxFontStyle)style, (wxFontWeight)weight, underlined, face, encoding); } bool wxFont::Create(wxSize size, wxFontFamily family, wxFontStyle style, wxFontWeight weight, bool underlined, const wxString& face, wxFontEncoding encoding ) { UnRef(); m_refData = new wxFontRefData(InfoFromLegacyParams(size.GetHeight(), family, style, weight, underlined, face, encoding)); return true; } float wxFont::GetFractionalPointSize() const { return M_FONTDATA.GetFractionalPointSize(); } wxFontStyle wxFont::GetStyle() const { return M_FONTDATA.GetStyle(); } int wxFont::GetNumericWeight() const { return M_FONTDATA.GetNumericWeight(); } bool wxFont::GetUnderlined() const { return M_FONTDATA.GetUnderlined(); } wxString wxFont::GetFaceName() const { return M_FONTDATA.GetFaceName(); } wxFontEncoding wxFont::GetEncoding() const { return M_FONTDATA.GetEncoding(); } const wxNativeFontInfo *wxFont::GetNativeFontInfo() const { return &M_FONTDATA; } void wxFont::SetFractionalPointSize(float pointSize) { AllocExclusive(); M_FONTDATA.SetFractionalPointSize(pointSize); } bool wxFont::SetFaceName(const wxString& facename) { AllocExclusive(); return M_FONTDATA.SetFaceName(facename); } void wxFont::SetFamily( wxFontFamily family ) { AllocExclusive(); M_FONTDATA.SetFamily(family); } void wxFont::SetStyle( wxFontStyle style ) { AllocExclusive(); M_FONTDATA.SetStyle(style); } void wxFont::SetNumericWeight(int weight) { AllocExclusive(); M_FONTDATA.SetNumericWeight(weight); } void wxFont::SetUnderlined( bool underlined ) { AllocExclusive(); M_FONTDATA.SetUnderlined(underlined); } void wxFont::SetEncoding(wxFontEncoding encoding) { AllocExclusive(); M_FONTDATA.SetEncoding(encoding); } wxGDIRefData *wxFont::CreateGDIRefData() const { return new wxFontRefData; } wxGDIRefData *wxFont::CloneGDIRefData(const wxGDIRefData *data) const { return new wxFontRefData(*(wxFontRefData *)data); } QFont wxFont::GetHandle() const { return M_FONTDATA.m_qtFont; } wxFontFamily wxFont::DoGetFamily() const { return M_FONTDATA.GetFamily(); } // ---------------------------------------------------------------------------- // wxNativeFontInfo // ---------------------------------------------------------------------------- void wxNativeFontInfo::Init() { } float wxNativeFontInfo::GetFractionalPointSize() const { return m_qtFont.pointSizeF(); } wxFontStyle wxNativeFontInfo::GetStyle() const { switch (m_qtFont.style()) { case QFont::StyleNormal: return wxFONTSTYLE_NORMAL; case QFont::StyleItalic: return wxFONTSTYLE_ITALIC; case QFont::StyleOblique: return wxFONTSTYLE_SLANT; } wxFAIL_MSG( "Invalid font style value" ); return wxFontStyle(); } int wxNativeFontInfo::GetNumericWeight() const { int w = m_qtFont.weight(); // Special case of wxQFont_Thin == 0. if ( w == wxQFont_Thin ) return wxFONTWEIGHT_THIN; if ( TryToMap(w, wxQFont_Thin, wxQFont_ExtraLight, wxFONTWEIGHT_THIN, wxFONTWEIGHT_EXTRALIGHT) || TryToMap(w, wxQFont_ExtraLight, wxQFont_Light, wxFONTWEIGHT_EXTRALIGHT, wxFONTWEIGHT_LIGHT) || TryToMap(w, wxQFont_Light, wxQFont_Normal, wxFONTWEIGHT_LIGHT, wxFONTWEIGHT_NORMAL) || TryToMap(w, wxQFont_Normal, wxQFont_Medium, wxFONTWEIGHT_NORMAL, wxFONTWEIGHT_MEDIUM) || TryToMap(w, wxQFont_Medium, wxQFont_DemiBold, wxFONTWEIGHT_MEDIUM, wxFONTWEIGHT_SEMIBOLD) || TryToMap(w, wxQFont_DemiBold, wxQFont_Bold, wxFONTWEIGHT_SEMIBOLD, wxFONTWEIGHT_BOLD) || TryToMap(w, wxQFont_Bold, wxQFont_ExtraBold, wxFONTWEIGHT_BOLD, wxFONTWEIGHT_EXTRABOLD) || TryToMap(w, wxQFont_ExtraBold, wxQFont_Black, wxFONTWEIGHT_EXTRABOLD, wxFONTWEIGHT_HEAVY) || TryToMap(w, wxQFont_Black, 99, wxFONTWEIGHT_HEAVY, wxFONTWEIGHT_EXTRAHEAVY) ) { return w; } wxFAIL_MSG( "Invalid QFont weight" ); return wxFONTWEIGHT_NORMAL; } bool wxNativeFontInfo::GetUnderlined() const { return m_qtFont.underline(); } bool wxNativeFontInfo::GetStrikethrough() const { return m_qtFont.strikeOut(); } wxString wxNativeFontInfo::GetFaceName() const { // use font info to get the matched face name (not the family given) QFontInfo info = QFontInfo(m_qtFont); return wxQtConvertString(info.family()); } wxFontFamily wxNativeFontInfo::GetFamily() const { switch (m_qtFont.styleHint()) { case QFont::System: case QFont::AnyStyle: return wxFONTFAMILY_DEFAULT; case QFont::Fantasy: case QFont::Cursive: case QFont::Decorative: return wxFONTFAMILY_DECORATIVE; case QFont::Serif: return wxFONTFAMILY_ROMAN; case QFont::SansSerif: return wxFONTFAMILY_SWISS; case QFont::Monospace: case QFont::TypeWriter: return wxFONTFAMILY_TELETYPE; } return wxFONTFAMILY_UNKNOWN; } wxFontEncoding wxNativeFontInfo::GetEncoding() const { // QFontInfo info = QFontInfo(m_qtFont); wxMISSING_IMPLEMENTATION( __FUNCTION__ ); return wxFONTENCODING_MAX; } void wxNativeFontInfo::SetFractionalPointSize(float pointsize) { m_qtFont.setPointSizeF(pointsize); } void wxNativeFontInfo::SetPixelSize(const wxSize& size) { m_qtFont.setPixelSize(size.GetHeight()); } void wxNativeFontInfo::SetStyle(wxFontStyle style) { switch(style) { case wxFONTSTYLE_ITALIC: m_qtFont.setStyle(QFont::StyleItalic); break; case wxFONTSTYLE_NORMAL: m_qtFont.setStyle(QFont::StyleNormal); break; case wxFONTSTYLE_SLANT: m_qtFont.setStyle(QFont::StyleOblique); break; } } void wxNativeFontInfo::SetNumericWeight(int weight) { m_qtFont.setWeight(ConvertFontWeight(weight)); } void wxNativeFontInfo::SetUnderlined(bool underlined) { m_qtFont.setUnderline(underlined); } void wxNativeFontInfo::SetStrikethrough(bool strikethrough) { m_qtFont.setStrikeOut(strikethrough); } bool wxNativeFontInfo::SetFaceName(const wxString& facename) { m_qtFont.setFamily(wxQtConvertString(facename)); // qt uses a "font matching algoritm" so the font will be allways valid return true; } void wxNativeFontInfo::SetFamily(wxFontFamily family) { m_qtFont.setStyleHint(ConvertFontFamily(family)); // reset the face name to force qt to choose a new font m_qtFont.setFamily(""); } void wxNativeFontInfo::SetEncoding(wxFontEncoding WXUNUSED(encoding)) { wxMISSING_IMPLEMENTATION( __FUNCTION__ ); } bool wxNativeFontInfo::FromString(const wxString& s) { return m_qtFont.fromString( wxQtConvertString( s ) ); } wxString wxNativeFontInfo::ToString() const { return wxQtConvertString( m_qtFont.toString() ); } bool wxNativeFontInfo::FromUserString(const wxString& s) { return FromString(s); } wxString wxNativeFontInfo::ToUserString() const { return ToString(); }