mtollari 4db94043cb Patch level : 12.0 no-patch
Files correlati     : 
Commento            : Spostamento in libraries delle librerie esterne di Campo per una maggiore pulizia e organizzazione

git-svn-id: svn://10.65.10.50/branches/R_10_00@24150 c028cbd2-c16b-5b4b-a496-9718f37d4682
2017-10-26 09:11:15 +00:00

785 lines
21 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: src/common/fontcmn.cpp
// Purpose: implementation of wxFontBase methods
// Author: Vadim Zeitlin
// Modified by:
// Created: 20.09.99
// RCS-ID: $Id: fontcmn.cpp 43661 2006-11-26 20:18:53Z VZ $
// Copyright: (c) wxWidgets team
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#include "wx/font.h"
#ifndef WX_PRECOMP
#include "wx/dc.h"
#include "wx/intl.h"
#include "wx/dcscreen.h"
#include "wx/log.h"
#include "wx/gdicmn.h"
#endif // WX_PRECOMP
#if defined(__WXMSW__)
#include "wx/msw/private.h" // includes windows.h for LOGFONT
#include "wx/msw/winundef.h"
#endif
#include "wx/fontutil.h" // for wxNativeFontInfo
#include "wx/fontmap.h"
#include "wx/fontenum.h"
#include "wx/tokenzr.h"
// ============================================================================
// implementation
// ============================================================================
// ----------------------------------------------------------------------------
// helper functions
// ----------------------------------------------------------------------------
static void AdjustFontSize(wxFont& font, wxDC& dc, const wxSize& pixelSize)
{
int currentSize = 0;
int largestGood = 0;
int smallestBad = 0;
bool initialGoodFound = false;
bool initialBadFound = false;
// NB: this assignment was separated from the variable definition
// in order to fix a gcc v3.3.3 compiler crash
currentSize = font.GetPointSize();
while (currentSize > 0)
{
dc.SetFont(font);
// if currentSize (in points) results in a font that is smaller
// than required by pixelSize it is considered a good size
if (dc.GetCharHeight() <= pixelSize.GetHeight() &&
(!pixelSize.GetWidth() ||
dc.GetCharWidth() <= pixelSize.GetWidth()))
{
largestGood = currentSize;
initialGoodFound = true;
}
else
{
smallestBad = currentSize;
initialBadFound = true;
}
if (!initialGoodFound)
{
currentSize /= 2;
}
else if (!initialBadFound)
{
currentSize *= 2;
}
else
{
int distance = smallestBad - largestGood;
if (distance == 1)
break;
currentSize = largestGood + distance / 2;
}
font.SetPointSize(currentSize);
}
if (currentSize != largestGood)
font.SetPointSize(largestGood);
}
// ----------------------------------------------------------------------------
// wxFontBase
// ----------------------------------------------------------------------------
wxFontEncoding wxFontBase::ms_encodingDefault = wxFONTENCODING_SYSTEM;
/* static */
void wxFontBase::SetDefaultEncoding(wxFontEncoding encoding)
{
// GetDefaultEncoding() should return something != wxFONTENCODING_DEFAULT
// and, besides, using this value here doesn't make any sense
wxCHECK_RET( encoding != wxFONTENCODING_DEFAULT,
_T("can't set default encoding to wxFONTENCODING_DEFAULT") );
ms_encodingDefault = encoding;
}
wxFontBase::~wxFontBase()
{
// this destructor is required for Darwin
}
/* static */
wxFont *wxFontBase::New(int size,
int family,
int style,
int weight,
bool underlined,
const wxString& face,
wxFontEncoding encoding)
{
return new wxFont(size, family, style, weight, underlined, face, encoding);
}
static inline int flags2Style(int flags)
{
return flags & wxFONTFLAG_ITALIC
? wxFONTSTYLE_ITALIC
: flags & wxFONTFLAG_SLANT
? wxFONTSTYLE_SLANT
: wxFONTSTYLE_NORMAL;
}
static inline int flags2Weight(int flags)
{
return flags & wxFONTFLAG_LIGHT
? wxFONTWEIGHT_LIGHT
: flags & wxFONTFLAG_BOLD
? wxFONTWEIGHT_BOLD
: wxFONTWEIGHT_NORMAL;
}
static inline bool flags2Underlined(int flags)
{
return (flags & wxFONTFLAG_UNDERLINED) != 0;
}
/* static */
wxFont *wxFontBase::New(int pointSize,
wxFontFamily family,
int flags,
const wxString& face,
wxFontEncoding encoding)
{
return New(pointSize, family, flags2Style(flags), flags2Weight(flags),
flags2Underlined(flags), face, encoding);
}
/* static */
wxFont *wxFontBase::New(const wxSize& pixelSize,
int family,
int style,
int weight,
bool underlined,
const wxString& face,
wxFontEncoding encoding)
{
#if defined(__WXMSW__)
return new wxFont(pixelSize, family, style, weight, underlined,
face, encoding);
#else
wxFont *self = New(10, family, style, weight, underlined, face, encoding);
wxScreenDC dc;
AdjustFontSize(*(wxFont *)self, dc, pixelSize);
return self;
#endif
}
/* static */
wxFont *wxFontBase::New(const wxSize& pixelSize,
wxFontFamily family,
int flags,
const wxString& face,
wxFontEncoding encoding)
{
return New(pixelSize, family, flags2Style(flags), flags2Weight(flags),
flags2Underlined(flags), face, encoding);
}
wxSize wxFontBase::GetPixelSize() const
{
wxScreenDC dc;
dc.SetFont(*(wxFont *)this);
return wxSize(dc.GetCharWidth(), dc.GetCharHeight());
}
bool wxFontBase::IsUsingSizeInPixels() const
{
return false;
}
void wxFontBase::SetPixelSize( const wxSize& pixelSize )
{
wxScreenDC dc;
AdjustFontSize(*(wxFont *)this, dc, pixelSize);
}
/* static */
wxFont *wxFontBase::New(const wxNativeFontInfo& info)
{
return new wxFont(info);
}
/* static */
wxFont *wxFontBase::New(const wxString& strNativeFontDesc)
{
wxNativeFontInfo fontInfo;
if ( !fontInfo.FromString(strNativeFontDesc) )
return new wxFont(*wxNORMAL_FONT);
return New(fontInfo);
}
bool wxFontBase::IsFixedWidth() const
{
return GetFamily() == wxFONTFAMILY_TELETYPE;
}
void wxFontBase::DoSetNativeFontInfo(const wxNativeFontInfo& info)
{
#ifdef wxNO_NATIVE_FONTINFO
SetPointSize(info.pointSize);
SetFamily(info.family);
SetStyle(info.style);
SetWeight(info.weight);
SetUnderlined(info.underlined);
SetFaceName(info.faceName);
SetEncoding(info.encoding);
#else
(void)info;
#endif
}
wxString wxFontBase::GetNativeFontInfoDesc() const
{
wxString fontDesc;
const wxNativeFontInfo *fontInfo = GetNativeFontInfo();
if ( fontInfo )
{
fontDesc = fontInfo->ToString();
wxASSERT_MSG(!fontDesc.empty(), wxT("This should be a non-empty string!"));
}
else
{
wxFAIL_MSG(wxT("Derived class should have created the wxNativeFontInfo!"));
}
return fontDesc;
}
wxString wxFontBase::GetNativeFontInfoUserDesc() const
{
wxString fontDesc;
const wxNativeFontInfo *fontInfo = GetNativeFontInfo();
if ( fontInfo )
{
fontDesc = fontInfo->ToUserString();
wxASSERT_MSG(!fontDesc.empty(), wxT("This should be a non-empty string!"));
}
else
{
wxFAIL_MSG(wxT("Derived class should have created the wxNativeFontInfo!"));
}
return fontDesc;
}
bool wxFontBase::SetNativeFontInfo(const wxString& info)
{
wxNativeFontInfo fontInfo;
if ( !info.empty() && fontInfo.FromString(info) )
{
SetNativeFontInfo(fontInfo);
return true;
}
UnRef();
return false;
}
bool wxFontBase::SetNativeFontInfoUserDesc(const wxString& info)
{
wxNativeFontInfo fontInfo;
if ( !info.empty() && fontInfo.FromUserString(info) )
{
SetNativeFontInfo(fontInfo);
return true;
}
UnRef();
return false;
}
bool wxFontBase::operator==(const wxFont& font) const
{
// either it is the same font, i.e. they share the same common data or they
// have different ref datas but still describe the same font
return IsSameAs(font) ||
(
Ok() == font.Ok() &&
GetPointSize() == font.GetPointSize() &&
// in wxGTK1 GetPixelSize() calls GetInternalFont() which uses
// operator==() resulting in infinite recursion so we can't use it
// in that port
#if !defined(__WXGTK__) || defined(__WXGTK20__)
GetPixelSize() == font.GetPixelSize() &&
#endif
GetFamily() == font.GetFamily() &&
GetStyle() == font.GetStyle() &&
GetWeight() == font.GetWeight() &&
GetUnderlined() == font.GetUnderlined() &&
GetFaceName().IsSameAs(font.GetFaceName(), false) &&
GetEncoding() == font.GetEncoding()
);
}
bool wxFontBase::operator!=(const wxFont& font) const
{
return !(*this == font);
}
wxString wxFontBase::GetFamilyString() const
{
wxCHECK_MSG( Ok(), wxT("wxDEFAULT"), wxT("invalid font") );
switch ( GetFamily() )
{
case wxDECORATIVE: return wxT("wxDECORATIVE");
case wxROMAN: return wxT("wxROMAN");
case wxSCRIPT: return wxT("wxSCRIPT");
case wxSWISS: return wxT("wxSWISS");
case wxMODERN: return wxT("wxMODERN");
case wxTELETYPE: return wxT("wxTELETYPE");
default: return wxT("wxDEFAULT");
}
}
wxString wxFontBase::GetStyleString() const
{
wxCHECK_MSG( Ok(), wxT("wxDEFAULT"), wxT("invalid font") );
switch ( GetStyle() )
{
case wxNORMAL: return wxT("wxNORMAL");
case wxSLANT: return wxT("wxSLANT");
case wxITALIC: return wxT("wxITALIC");
default: return wxT("wxDEFAULT");
}
}
wxString wxFontBase::GetWeightString() const
{
wxCHECK_MSG( Ok(), wxT("wxDEFAULT"), wxT("invalid font") );
switch ( GetWeight() )
{
case wxNORMAL: return wxT("wxNORMAL");
case wxBOLD: return wxT("wxBOLD");
case wxLIGHT: return wxT("wxLIGHT");
default: return wxT("wxDEFAULT");
}
}
bool wxFontBase::SetFaceName(const wxString &facename)
{
if (!wxFontEnumerator::IsValidFacename(facename))
{
UnRef(); // make Ok() return false
return false;
}
return true;
}
// ----------------------------------------------------------------------------
// wxNativeFontInfo
// ----------------------------------------------------------------------------
// Up to now, there are no native implementations of this function:
void wxNativeFontInfo::SetFaceName(const wxArrayString &facenames)
{
for (size_t i=0; i < facenames.GetCount(); i++)
{
if (wxFontEnumerator::IsValidFacename(facenames[i]))
{
SetFaceName(facenames[i]);
return;
}
}
// set the first valid facename we can find on this system
wxString validfacename = wxFontEnumerator::GetFacenames().Item(0);
wxLogTrace(wxT("font"), wxT("Falling back to '%s'"), validfacename.c_str());
SetFaceName(validfacename);
}
#ifdef wxNO_NATIVE_FONTINFO
// These are the generic forms of FromString()/ToString.
//
// convert to/from the string representation: format is
// version;pointsize;family;style;weight;underlined;facename;encoding
bool wxNativeFontInfo::FromString(const wxString& s)
{
long l;
wxStringTokenizer tokenizer(s, _T(";"));
wxString token = tokenizer.GetNextToken();
//
// Ignore the version for now
//
token = tokenizer.GetNextToken();
if ( !token.ToLong(&l) )
return false;
pointSize = (int)l;
token = tokenizer.GetNextToken();
if ( !token.ToLong(&l) )
return false;
family = (wxFontFamily)l;
token = tokenizer.GetNextToken();
if ( !token.ToLong(&l) )
return false;
style = (wxFontStyle)l;
token = tokenizer.GetNextToken();
if ( !token.ToLong(&l) )
return false;
weight = (wxFontWeight)l;
token = tokenizer.GetNextToken();
if ( !token.ToLong(&l) )
return false;
underlined = l != 0;
faceName = tokenizer.GetNextToken();
#ifndef __WXMAC__
if( !faceName )
return false;
#endif
token = tokenizer.GetNextToken();
if ( !token.ToLong(&l) )
return false;
encoding = (wxFontEncoding)l;
return true;
}
wxString wxNativeFontInfo::ToString() const
{
wxString s;
s.Printf(_T("%d;%d;%d;%d;%d;%d;%s;%d"),
0, // version
pointSize,
family,
(int)style,
(int)weight,
underlined,
faceName.GetData(),
(int)encoding);
return s;
}
void wxNativeFontInfo::Init()
{
pointSize = 0;
family = wxFONTFAMILY_DEFAULT;
style = wxFONTSTYLE_NORMAL;
weight = wxFONTWEIGHT_NORMAL;
underlined = false;
faceName.clear();
encoding = wxFONTENCODING_DEFAULT;
}
int wxNativeFontInfo::GetPointSize() const
{
return pointSize;
}
wxFontStyle wxNativeFontInfo::GetStyle() const
{
return style;
}
wxFontWeight wxNativeFontInfo::GetWeight() const
{
return weight;
}
bool wxNativeFontInfo::GetUnderlined() const
{
return underlined;
}
wxString wxNativeFontInfo::GetFaceName() const
{
return faceName;
}
wxFontFamily wxNativeFontInfo::GetFamily() const
{
return family;
}
wxFontEncoding wxNativeFontInfo::GetEncoding() const
{
return encoding;
}
void wxNativeFontInfo::SetPointSize(int pointsize)
{
pointSize = pointsize;
}
void wxNativeFontInfo::SetStyle(wxFontStyle style_)
{
style = style_;
}
void wxNativeFontInfo::SetWeight(wxFontWeight weight_)
{
weight = weight_;
}
void wxNativeFontInfo::SetUnderlined(bool underlined_)
{
underlined = underlined_;
}
bool wxNativeFontInfo::SetFaceName(const wxString& facename_)
{
faceName = facename_;
return true;
}
void wxNativeFontInfo::SetFamily(wxFontFamily family_)
{
family = family_;
}
void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding_)
{
encoding = encoding_;
}
#endif // generic wxNativeFontInfo implementation
// conversion to/from user-readable string: this is used in the generic
// versions and under MSW as well because there is no standard font description
// format there anyhow (but there is a well-defined standard for X11 fonts used
// by wxGTK and wxMotif)
#if defined(wxNO_NATIVE_FONTINFO) || defined(__WXMSW__) || defined (__WXPM__)
wxString wxNativeFontInfo::ToUserString() const
{
wxString desc;
// first put the adjectives, if any - this is English-centric, of course,
// but what else can we do?
if ( GetUnderlined() )
{
desc << _("underlined");
}
switch ( GetWeight() )
{
default:
wxFAIL_MSG( _T("unknown font weight") );
// fall through
case wxFONTWEIGHT_NORMAL:
break;
case wxFONTWEIGHT_LIGHT:
desc << _(" light");
break;
case wxFONTWEIGHT_BOLD:
desc << _(" bold");
break;
}
switch ( GetStyle() )
{
default:
wxFAIL_MSG( _T("unknown font style") );
// fall through
case wxFONTSTYLE_NORMAL:
break;
// we don't distinguish between the two for now anyhow...
case wxFONTSTYLE_ITALIC:
case wxFONTSTYLE_SLANT:
desc << _(" italic");
break;
}
wxString face = GetFaceName();
if ( !face.empty() )
{
desc << _T(' ') << face;
}
int size = GetPointSize();
if ( size != wxNORMAL_FONT->GetPointSize() )
{
desc << _T(' ') << size;
}
#if wxUSE_FONTMAP
wxFontEncoding enc = GetEncoding();
if ( enc != wxFONTENCODING_DEFAULT && enc != wxFONTENCODING_SYSTEM )
{
desc << _T(' ') << wxFontMapper::GetEncodingName(enc);
}
#endif // wxUSE_FONTMAP
return desc.Strip(wxString::both).MakeLower();
}
bool wxNativeFontInfo::FromUserString(const wxString& s)
{
// reset to the default state
Init();
// parse a more or less free form string
//
// TODO: we should handle at least the quoted facenames
wxStringTokenizer tokenizer(s, _T(";, "), wxTOKEN_STRTOK);
wxString face;
unsigned long size;
bool weightfound = false, pointsizefound = false;
#if wxUSE_FONTMAP
bool encodingfound = false;
#endif
while ( tokenizer.HasMoreTokens() )
{
wxString token = tokenizer.GetNextToken();
// normalize it
token.Trim(true).Trim(false).MakeLower();
// look for the known tokens
if ( token == _T("underlined") || token == _("underlined") )
{
SetUnderlined(true);
}
else if ( token == _T("light") || token == _("light") )
{
SetWeight(wxFONTWEIGHT_LIGHT);
weightfound = true;
}
else if ( token == _T("bold") || token == _("bold") )
{
SetWeight(wxFONTWEIGHT_BOLD);
weightfound = true;
}
else if ( token == _T("italic") || token == _("italic") )
{
SetStyle(wxFONTSTYLE_ITALIC);
}
else if ( token.ToULong(&size) )
{
SetPointSize(size);
pointsizefound = true;
}
else
{
#if wxUSE_FONTMAP
// try to interpret this as an encoding
wxFontEncoding encoding = wxFontMapper::Get()->CharsetToEncoding(token, false);
if ( encoding != wxFONTENCODING_DEFAULT &&
encoding != wxFONTENCODING_SYSTEM ) // returned when the recognition failed
{
SetEncoding(encoding);
encodingfound = true;
}
else
{
#endif // wxUSE_FONTMAP
// assume it is the face name
if ( !face.empty() )
{
face += _T(' ');
}
face += token;
// skip the code which resets face below
continue;
#if wxUSE_FONTMAP
}
#endif // wxUSE_FONTMAP
}
// if we had had the facename, we shouldn't continue appending tokens
// to it (i.e. "foo bold bar" shouldn't result in the facename "foo
// bar")
if ( !face.empty() )
{
// NB: the check on the facename is implemented in wxFontBase::SetFaceName
// and not in wxNativeFontInfo::SetFaceName thus we need to explicitely
// call here wxFontEnumerator::IsValidFacename
if (!wxFontEnumerator::IsValidFacename(face) ||
!SetFaceName(face))
SetFaceName(wxNORMAL_FONT->GetFaceName());
face.clear();
}
}
// we might not have flushed it inside the loop
if ( !face.empty() )
{
// NB: the check on the facename is implemented in wxFontBase::SetFaceName
// and not in wxNativeFontInfo::SetFaceName thus we need to explicitely
// call here wxFontEnumerator::IsValidFacename
if (!wxFontEnumerator::IsValidFacename(face) ||
!SetFaceName(face))
SetFaceName(wxNORMAL_FONT->GetFaceName());
}
// set point size to default value if size was not given
if ( !pointsizefound )
SetPointSize(wxNORMAL_FONT->GetPointSize());
// set font weight to default value if weight was not given
if ( !weightfound )
SetWeight(wxFONTWEIGHT_NORMAL);
#if wxUSE_FONTMAP
// set font encoding to default value if encoding was not given
if ( !encodingfound )
SetEncoding(wxFONTENCODING_SYSTEM);
#endif // wxUSE_FONTMAP
return true;
}
#endif // generic or wxMSW or wxOS2