From a73194f6b448b047168c566e48837957d08d2165 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 16 Jan 2020 00:07:06 +0100 Subject: [PATCH] Allow parsing all fractional sizes in wxFont descriptions Remove the check that the size representation was the same as float and as double, which was supposed to catch various edge cases (NaNs, huge numbers etc) but actually caught plenty of perfectly valid font sizes such as 13.8 that simply lost precision when converting from double to float. Just check that the size is positive and less than FLT_MAX to avoid using values that really don't make sense as font sizes. Also add a unit test checking that using fractional font sizes in description string works as expected. Closes #18590. Closes https://github.com/wxWidgets/wxWidgets/pull/1707 --- src/common/fontcmn.cpp | 6 ++++-- src/msw/font.cpp | 7 +++++-- src/osx/carbon/font.cpp | 6 ++++-- tests/font/fonttest.cpp | 24 ++++++++++++++++++++++++ 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/common/fontcmn.cpp b/src/common/fontcmn.cpp index 7767791433..cadf89b1e5 100644 --- a/src/common/fontcmn.cpp +++ b/src/common/fontcmn.cpp @@ -44,6 +44,8 @@ #include "wx/tokenzr.h" +#include // for FLT_MAX + // debugger helper: this function can be called from a debugger to show what // the date really is extern const char *wxDumpFont(const wxFont *font) @@ -758,9 +760,9 @@ bool wxNativeFontInfo::FromString(const wxString& s) token = tokenizer.GetNextToken(); if ( !token.ToCDouble(&d) ) return false; - pointSize = static_cast(d); - if ( static_cast(pointSize) != d ) + if ( d < 0 || d > FLT_MAX ) return false; + pointSize = static_cast(d); token = tokenizer.GetNextToken(); if ( !token.ToLong(&l) ) diff --git a/src/msw/font.cpp b/src/msw/font.cpp index c54e2601ad..293c8e0324 100644 --- a/src/msw/font.cpp +++ b/src/msw/font.cpp @@ -43,6 +43,8 @@ #include "wx/scopeguard.h" #include "wx/tokenzr.h" +#include // for FLT_MAX + // ---------------------------------------------------------------------------- // constants // ---------------------------------------------------------------------------- @@ -692,10 +694,11 @@ bool wxNativeFontInfo::FromString(const wxString& s) // lfHeight, as with v0 strings. if ( !wxIsNullDouble(d) ) { - pointSize = static_cast(d); - if ( static_cast(pointSize) != d ) + if ( d < 0 || d > FLT_MAX ) return false; + pointSize = static_cast(d); + setPointSizeFromHeight = false; } } diff --git a/src/osx/carbon/font.cpp b/src/osx/carbon/font.cpp index c1dcc0fda0..8504b4c609 100644 --- a/src/osx/carbon/font.cpp +++ b/src/osx/carbon/font.cpp @@ -31,6 +31,8 @@ #include #include +#include // for FLT_MAX + #define TRACE_CTFONT "ctfont" class WXDLLEXPORT wxFontRefData : public wxGDIRefData @@ -957,13 +959,13 @@ bool wxNativeFontInfo::FromString(const wxString& s) token = tokenizer.GetNextToken(); if ( !token.ToCDouble(&d) ) return false; + if ( d < 0 || d > FLT_MAX ) + return false; #ifdef __LP64__ // CGFloat is just double in this case. m_ctSize = d; #else // !__LP64__ m_ctSize = static_cast(d); - if ( static_cast(m_ctSize) != d ) - return false; #endif // __LP64__/!__LP64__ token = tokenizer.GetNextToken(); diff --git a/tests/font/fonttest.cpp b/tests/font/fonttest.cpp index b6cd5b60aa..f3e53ad74d 100644 --- a/tests/font/fonttest.cpp +++ b/tests/font/fonttest.cpp @@ -449,4 +449,28 @@ TEST_CASE("wxFont::NativeFontInfoUserDesc", "[font][fontinfo]") 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 float sizes[] = { 12.0f, 10.5f, 13.8f, 10.123f, 11.1f }; + 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 float 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 ); + } }