896512c732
There doesn't seem to be any compelling reason to use float. Using double is simpler, and avoids otherwise unnecessary float<->double conversions.
477 lines
15 KiB
C++
477 lines
15 KiB
C++
///////////////////////////////////////////////////////////////////////////////
|
|
// Name: tests/font/fonttest.cpp
|
|
// Purpose: wxFont unit test
|
|
// Author: Francesco Montorsi
|
|
// Created: 16.3.09
|
|
// Copyright: (c) 2009 Francesco Montorsi
|
|
// Licence: wxWindows licence
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// headers
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#include "testprec.h"
|
|
|
|
#ifdef __BORLANDC__
|
|
#pragma hdrstop
|
|
#endif
|
|
|
|
#ifndef WX_PRECOMP
|
|
#include "wx/wx.h"
|
|
#endif // WX_PRECOMP
|
|
|
|
#include "wx/font.h"
|
|
|
|
#include "asserthelper.h"
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// local helpers
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// Returns a point to an array of fonts and fills the output parameter with the
|
|
// number of elements in this array.
|
|
static const wxFont *GetTestFonts(unsigned& numFonts)
|
|
{
|
|
static const wxFont testfonts[] =
|
|
{
|
|
*wxNORMAL_FONT,
|
|
*wxSMALL_FONT,
|
|
*wxITALIC_FONT,
|
|
*wxSWISS_FONT,
|
|
wxFont(5, wxFONTFAMILY_TELETYPE, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL)
|
|
};
|
|
|
|
numFonts = WXSIZEOF(testfonts);
|
|
|
|
return testfonts;
|
|
}
|
|
|
|
wxString DumpFont(const wxFont *font)
|
|
{
|
|
// dumps the internal properties of a wxFont in the same order they
|
|
// are checked by wxFontBase::operator==()
|
|
|
|
wxASSERT(font->IsOk());
|
|
|
|
wxString s;
|
|
s.Printf(wxS("%d-%d;%d-%d-%d-%d-%d-%s-%d"),
|
|
font->GetPointSize(),
|
|
font->GetPixelSize().x,
|
|
font->GetPixelSize().y,
|
|
font->GetFamily(),
|
|
font->GetStyle(),
|
|
font->GetWeight(),
|
|
font->GetUnderlined() ? 1 : 0,
|
|
font->GetFaceName(),
|
|
font->GetEncoding());
|
|
|
|
return s;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// the tests
|
|
// ----------------------------------------------------------------------------
|
|
|
|
TEST_CASE("wxFont::Construct", "[font][ctor]")
|
|
{
|
|
// The main purpose of this test is to verify that the font ctors below
|
|
// compile because it's easy to introduce ambiguities due to the number of
|
|
// overloaded wxFont ctors.
|
|
|
|
CHECK( wxFont(10, wxFONTFAMILY_DEFAULT,
|
|
wxFONTSTYLE_NORMAL,
|
|
wxFONTWEIGHT_NORMAL).IsOk() );
|
|
|
|
#if WXWIN_COMPATIBILITY_3_0
|
|
// Disable the warning about deprecated wxNORMAL as we use it here
|
|
// intentionally.
|
|
#ifdef __VISUALC__
|
|
#pragma warning(push)
|
|
#pragma warning(disable:4996)
|
|
#endif
|
|
|
|
wxGCC_WARNING_SUPPRESS(deprecated-declarations)
|
|
|
|
// Tests relying on the soon-to-be-deprecated ctor taking ints and not
|
|
// wxFontXXX enum elements.
|
|
CHECK( wxFont(10, wxDEFAULT, wxNORMAL, wxNORMAL).IsOk() );
|
|
|
|
wxGCC_WARNING_RESTORE(deprecated-declarations)
|
|
|
|
#ifdef __VISUALC__
|
|
#pragma warning(pop)
|
|
#endif
|
|
#endif // WXWIN_COMPATIBILITY_3_0
|
|
}
|
|
|
|
TEST_CASE("wxFont::Size", "[font][size]")
|
|
{
|
|
const struct Sizes
|
|
{
|
|
int specified; // Size in points specified in the ctor.
|
|
int expected; // Expected GetPointSize() return value,
|
|
// -1 here means "same as wxNORMAL_FONT".
|
|
} sizes[] =
|
|
{
|
|
{ 9, 9 },
|
|
{ 10, 10 },
|
|
{ 11, 11 },
|
|
{ -1, -1 },
|
|
{ 70, -1 }, // 70 == wxDEFAULT, should be handled specially
|
|
{ 90, 90 }, // 90 == wxNORMAL, should not be handled specially
|
|
};
|
|
|
|
const int sizeDefault = wxFont(wxFontInfo()).GetPointSize();
|
|
|
|
for ( size_t n = 0; n < WXSIZEOF(sizes); n++ )
|
|
{
|
|
const Sizes& size = sizes[n];
|
|
|
|
// Note: use the old-style wxFont ctor as wxFontInfo doesn't implement
|
|
// any compatibility hacks.
|
|
const wxFont font(size.specified,
|
|
wxFONTFAMILY_DEFAULT,
|
|
wxFONTSTYLE_NORMAL,
|
|
wxFONTWEIGHT_NORMAL);
|
|
|
|
int expected = size.expected;
|
|
if ( expected == -1 )
|
|
expected = sizeDefault;
|
|
|
|
INFO("specified = " << size.specified <<
|
|
", expected = " << size.expected);
|
|
CHECK( font.GetPointSize() == expected );
|
|
}
|
|
|
|
// Note that the compatibility hacks only apply to the old ctors, the newer
|
|
// one, taking wxFontInfo, doesn't support them.
|
|
CHECK( wxFont(wxFontInfo(70)).GetPointSize() == 70 );
|
|
CHECK( wxFont(wxFontInfo(90)).GetPointSize() == 90 );
|
|
|
|
// Check fractional point sizes as well.
|
|
wxFont font(wxFontInfo(12.25));
|
|
CHECK( font.GetFractionalPointSize() == 12.25 );
|
|
CHECK( font.GetPointSize() == 12 );
|
|
|
|
font = *wxNORMAL_FONT;
|
|
font.SetFractionalPointSize(9.5);
|
|
CHECK( font.GetFractionalPointSize() == 9.5 );
|
|
CHECK( font.GetPointSize() == 10 );
|
|
}
|
|
|
|
TEST_CASE("wxFont::Style", "[font][style]")
|
|
{
|
|
#if WXWIN_COMPATIBILITY_3_0
|
|
// Disable the warning about deprecated wxNORMAL as we use it here
|
|
// intentionally.
|
|
#ifdef __VISUALC__
|
|
#pragma warning(push)
|
|
#pragma warning(disable:4996)
|
|
#endif
|
|
|
|
wxGCC_WARNING_SUPPRESS(deprecated-declarations)
|
|
|
|
wxFont fontNormal(10, wxDEFAULT, wxNORMAL, wxNORMAL);
|
|
CHECK( fontNormal.GetStyle() == wxFONTSTYLE_NORMAL );
|
|
|
|
wxFont fontItalic(10, wxDEFAULT, wxITALIC, wxNORMAL);
|
|
CHECK( fontItalic.GetStyle() == wxFONTSTYLE_ITALIC );
|
|
|
|
wxFont fontSlant(10, wxDEFAULT, wxSLANT, wxNORMAL);
|
|
#ifdef __WXMSW__
|
|
CHECK( fontSlant.GetStyle() == wxFONTSTYLE_ITALIC );
|
|
#else
|
|
CHECK( fontSlant.GetStyle() == wxFONTSTYLE_SLANT );
|
|
#endif
|
|
|
|
wxGCC_WARNING_RESTORE(deprecated-declarations)
|
|
|
|
#ifdef __VISUALC__
|
|
#pragma warning(pop)
|
|
#endif
|
|
#endif // WXWIN_COMPATIBILITY_3_0
|
|
}
|
|
|
|
TEST_CASE("wxFont::Weight", "[font][weight]")
|
|
{
|
|
wxFont font;
|
|
font.SetNumericWeight(123);
|
|
|
|
// WX to QT font weight conversions do not map directly which is why we
|
|
// check if the numeric weight is within a range rather than checking for
|
|
// an exact match.
|
|
#ifdef __WXQT__
|
|
CHECK( ( font.GetNumericWeight() > 113 && font.GetNumericWeight() < 133 ) );
|
|
#else
|
|
CHECK( font.GetNumericWeight() == 123 );
|
|
#endif
|
|
|
|
CHECK( font.GetWeight() == wxFONTWEIGHT_THIN );
|
|
|
|
font.SetNumericWeight(wxFONTWEIGHT_SEMIBOLD);
|
|
CHECK( font.GetNumericWeight() == wxFONTWEIGHT_SEMIBOLD );
|
|
CHECK( font.GetWeight() == wxFONTWEIGHT_SEMIBOLD );
|
|
|
|
#if WXWIN_COMPATIBILITY_3_0
|
|
// Disable the warning about deprecated wxNORMAL as we use it here
|
|
// intentionally.
|
|
#ifdef __VISUALC__
|
|
#pragma warning(push)
|
|
#pragma warning(disable:4996)
|
|
#endif
|
|
|
|
wxGCC_WARNING_SUPPRESS(deprecated-declarations)
|
|
|
|
wxFont fontNormal(10, wxDEFAULT, wxNORMAL, wxNORMAL);
|
|
CHECK( fontNormal.GetWeight() == wxFONTWEIGHT_NORMAL );
|
|
|
|
wxFont fontBold(10, wxDEFAULT, wxNORMAL, wxBOLD);
|
|
CHECK( fontBold.GetWeight() == wxFONTWEIGHT_BOLD );
|
|
|
|
wxFont fontLight(10, wxDEFAULT, wxNORMAL, wxLIGHT);
|
|
CHECK( fontLight.GetWeight() == wxFONTWEIGHT_LIGHT );
|
|
|
|
wxGCC_WARNING_RESTORE(deprecated-declarations)
|
|
|
|
#ifdef __VISUALC__
|
|
#pragma warning(pop)
|
|
#endif
|
|
#endif // WXWIN_COMPATIBILITY_3_0
|
|
}
|
|
|
|
TEST_CASE("wxFont::GetSet", "[font][getters]")
|
|
{
|
|
unsigned numFonts;
|
|
const wxFont *pf = GetTestFonts(numFonts);
|
|
for ( unsigned n = 0; n < numFonts; n++ )
|
|
{
|
|
wxFont test(*pf++);
|
|
|
|
// remember: getters can only be called when wxFont::IsOk() == true
|
|
CHECK( test.IsOk() );
|
|
|
|
|
|
// test Get/SetFaceName()
|
|
#ifndef __WXQT__
|
|
CHECK( !test.SetFaceName("a dummy face name") );
|
|
CHECK( !test.IsOk() );
|
|
#endif
|
|
|
|
// if the call to SetFaceName() below fails on your system/port,
|
|
// consider adding another branch to this #if
|
|
#if defined(__WXMSW__) || defined(__WXOSX__)
|
|
static const char *knownGoodFaceName = "Arial";
|
|
#else
|
|
static const char *knownGoodFaceName = "Monospace";
|
|
#endif
|
|
|
|
WX_ASSERT_MESSAGE
|
|
(
|
|
("failed to set face name \"%s\" for test font #%u\n"
|
|
"(this failure is harmless if this face name is not "
|
|
"available on this system)", knownGoodFaceName, n),
|
|
test.SetFaceName(knownGoodFaceName)
|
|
);
|
|
CHECK( test.IsOk() );
|
|
|
|
|
|
// test Get/SetFamily()
|
|
|
|
test.SetFamily( wxFONTFAMILY_ROMAN );
|
|
CHECK( test.IsOk() );
|
|
|
|
// note that there is always the possibility that GetFamily() returns
|
|
// wxFONTFAMILY_DEFAULT (meaning "unknown" in this case) so that we
|
|
// consider it as a valid return value
|
|
const wxFontFamily family = test.GetFamily();
|
|
if ( family != wxFONTFAMILY_DEFAULT )
|
|
CHECK( wxFONTFAMILY_ROMAN == family );
|
|
|
|
|
|
// test Get/SetEncoding()
|
|
|
|
//test.SetEncoding( wxFONTENCODING_KOI8 );
|
|
//CHECK( test.IsOk() );
|
|
//CHECK( wxFONTENCODING_KOI8 == test.GetEncoding() );
|
|
|
|
|
|
// test Get/SetPointSize()
|
|
|
|
test.SetPointSize(30);
|
|
CHECK( test.IsOk() );
|
|
CHECK( 30 == test.GetPointSize() );
|
|
|
|
|
|
// test Get/SetPixelSize()
|
|
|
|
test.SetPixelSize(wxSize(0,30));
|
|
CHECK( test.IsOk() );
|
|
CHECK( test.GetPixelSize().GetHeight() <= 30 );
|
|
// NOTE: the match found by SetPixelSize() may be not 100% precise; it
|
|
// only grants that a font smaller than the required height will
|
|
// be selected
|
|
|
|
|
|
// test Get/SetStyle()
|
|
|
|
test.SetStyle(wxFONTSTYLE_SLANT);
|
|
CHECK( test.IsOk() );
|
|
#ifdef __WXMSW__
|
|
// on wxMSW wxFONTSTYLE_SLANT==wxFONTSTYLE_ITALIC, so accept the latter
|
|
// as a valid value too.
|
|
if ( test.GetStyle() != wxFONTSTYLE_ITALIC )
|
|
#endif
|
|
CHECK( wxFONTSTYLE_SLANT == test.GetStyle() );
|
|
|
|
// test Get/SetUnderlined()
|
|
|
|
test.SetUnderlined(true);
|
|
CHECK( test.IsOk() );
|
|
CHECK( test.GetUnderlined() );
|
|
|
|
const wxFont fontBase = test.GetBaseFont();
|
|
CHECK( fontBase.IsOk() );
|
|
CHECK( !fontBase.GetUnderlined() );
|
|
CHECK( !fontBase.GetStrikethrough() );
|
|
CHECK( wxFONTWEIGHT_NORMAL == fontBase.GetWeight() );
|
|
CHECK( wxFONTSTYLE_NORMAL == fontBase.GetStyle() );
|
|
|
|
// test Get/SetStrikethrough()
|
|
|
|
test.SetStrikethrough(true);
|
|
CHECK( test.IsOk() );
|
|
CHECK( test.GetStrikethrough() );
|
|
|
|
|
|
// test Get/SetWeight()
|
|
|
|
test.SetWeight(wxFONTWEIGHT_BOLD);
|
|
CHECK( test.IsOk() );
|
|
CHECK( wxFONTWEIGHT_BOLD == test.GetWeight() );
|
|
}
|
|
}
|
|
|
|
TEST_CASE("wxFont::NativeFontInfo", "[font][fontinfo]")
|
|
{
|
|
unsigned numFonts;
|
|
const wxFont *pf = GetTestFonts(numFonts);
|
|
for ( unsigned n = 0; n < numFonts; n++ )
|
|
{
|
|
wxFont test(*pf++);
|
|
|
|
const wxString& nid = test.GetNativeFontInfoDesc();
|
|
CHECK( !nid.empty() );
|
|
// documented to be never empty
|
|
|
|
wxFont temp;
|
|
CHECK( temp.SetNativeFontInfo(nid) );
|
|
CHECK( temp.IsOk() );
|
|
WX_ASSERT_MESSAGE(
|
|
("Test #%u failed\ndump of test font: \"%s\"\ndump of temp font: \"%s\"", \
|
|
n, DumpFont(&test), DumpFont(&temp)),
|
|
temp == test );
|
|
}
|
|
|
|
// test that clearly invalid font info strings do not work
|
|
wxFont font;
|
|
CHECK( !font.SetNativeFontInfo("") );
|
|
|
|
// pango_font_description_from_string() used by wxFont in wxGTK and wxX11
|
|
// never returns an error at all so this assertion fails there -- and as it
|
|
// doesn't seem to be possible to do anything about it maybe we should
|
|
// change wxMSW and other ports to also accept any strings?
|
|
#if !defined(__WXGTK__) && !defined(__WXX11__) && !defined(__WXQT__)
|
|
CHECK( !font.SetNativeFontInfo("bloordyblop") );
|
|
#endif
|
|
|
|
// Pango font description doesn't have 'underlined' and 'strikethrough'
|
|
// attributes, so wxNativeFontInfo implements these itself. Test if these
|
|
// are properly preserved by wxNativeFontInfo or its string description.
|
|
font.SetUnderlined(true);
|
|
font.SetStrikethrough(true);
|
|
CHECK(font == wxFont(font));
|
|
CHECK(font == wxFont(*font.GetNativeFontInfo()));
|
|
CHECK(font == wxFont(font.GetNativeFontInfoDesc()));
|
|
font.SetUnderlined(false);
|
|
CHECK(font == wxFont(font));
|
|
CHECK(font == wxFont(*font.GetNativeFontInfo()));
|
|
CHECK(font == wxFont(font.GetNativeFontInfoDesc()));
|
|
font.SetUnderlined(true);
|
|
font.SetStrikethrough(false);
|
|
CHECK(font == wxFont(font));
|
|
CHECK(font == wxFont(*font.GetNativeFontInfo()));
|
|
CHECK(font == wxFont(font.GetNativeFontInfoDesc()));
|
|
// note: the GetNativeFontInfoUserDesc() doesn't preserve all attributes
|
|
// according to docs, so it is not tested.
|
|
}
|
|
|
|
TEST_CASE("wxFont::NativeFontInfoUserDesc", "[font][fontinfo]")
|
|
{
|
|
unsigned numFonts;
|
|
const wxFont *pf = GetTestFonts(numFonts);
|
|
for ( unsigned n = 0; n < numFonts; n++ )
|
|
{
|
|
wxFont test(*pf++);
|
|
|
|
const wxString& niud = test.GetNativeFontInfoUserDesc();
|
|
CHECK( !niud.empty() );
|
|
// documented to be never empty
|
|
|
|
wxFont temp2;
|
|
CHECK( temp2.SetNativeFontInfoUserDesc(niud) );
|
|
CHECK( temp2.IsOk() );
|
|
|
|
#ifdef __WXGTK__
|
|
// Pango saves/restores all font info in the user-friendly string:
|
|
WX_ASSERT_MESSAGE(
|
|
("Test #%u failed; native info user desc was \"%s\" for test and \"%s\" for temp2", \
|
|
n, niud, temp2.GetNativeFontInfoUserDesc()),
|
|
temp2 == test );
|
|
#else
|
|
// NOTE: as documented GetNativeFontInfoUserDesc/SetNativeFontInfoUserDesc
|
|
// are not granted to save/restore all font info.
|
|
// In fact e.g. the font family is not saved at all; test only those
|
|
// info which GetNativeFontInfoUserDesc() does indeed save:
|
|
CHECK( test.GetWeight() == temp2.GetWeight() );
|
|
CHECK( test.GetStyle() == temp2.GetStyle() );
|
|
|
|
// if the original face name was empty, it means that any face name (in
|
|
// this family) can be used for the new font so we shouldn't be
|
|
// surprised to find that they differ in this case
|
|
const wxString facename = test.GetFaceName();
|
|
if ( !facename.empty() )
|
|
{
|
|
CHECK( facename.Upper() == temp2.GetFaceName().Upper() );
|
|
}
|
|
|
|
CHECK( test.GetPointSize() == temp2.GetPointSize() );
|
|
CHECK( test.GetEncoding() == temp2.GetEncoding() );
|
|
#endif
|
|
}
|
|
|
|
// Test for a bug with handling fractional font sizes in description
|
|
// strings (see #18590).
|
|
wxFont font(*wxNORMAL_FONT);
|
|
|
|
static const double sizes[] = { 12.0, 10.5, 13.8, 10.123, 11.1 };
|
|
for ( unsigned n = 0; n < WXSIZEOF(sizes); n++ )
|
|
{
|
|
font.SetFractionalPointSize(sizes[n]);
|
|
|
|
// Just setting the font can slightly change it because of rounding
|
|
// errors, so don't expect the actual size to be exactly equal to what
|
|
// we used -- but close enough.
|
|
const double sizeUsed = font.GetFractionalPointSize();
|
|
CHECK( sizeUsed == Approx(sizes[n]).epsilon(0.001) );
|
|
|
|
const wxString& desc = font.GetNativeFontInfoDesc();
|
|
INFO("Font description: " << desc);
|
|
CHECK( font.SetNativeFontInfo(desc) );
|
|
|
|
// Notice that here we use the exact comparison, there is no reason for
|
|
// a differently rounded size to be used.
|
|
CHECK( font.GetFractionalPointSize() == sizeUsed );
|
|
}
|
|
}
|