539 lines
13 KiB
C++
539 lines
13 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// 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 <QtGui/QFont>
|
|
#include <QtGui/QFontInfo>
|
|
|
|
#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();
|
|
}
|