Minor optimizations in GetMultiLineTextExtent()

Handle the case of a single line string specially, it's faster to do
this than use slow loop over all characters.

Also avoid constructing the string with the characters to measure one by
one and do it all at once instead.

Add a possibility to benchmark GetMultiLineTextExtent() rather than
GetTextExtent() in the graphics benchmark.
This commit is contained in:
Vadim Zeitlin 2020-06-10 23:36:03 +02:00
parent 09ecfaec8f
commit bfeae1922d
2 changed files with 23 additions and 9 deletions

View File

@ -105,17 +105,27 @@ void wxTextMeasureBase::GetMultiLineTextExtent(const wxString& text,
wxCoord *height,
wxCoord *heightOneLine)
{
// It's noticeably faster to handle the case of a string which isn't
// actually multiline specially here, to skip iteration above in this case.
if ( text.find('\n') == wxString::npos )
{
GetTextExtent(text, width, height);
if ( heightOneLine && height )
*heightOneLine = *height;
return;
}
MeasuringGuard guard(*this);
wxCoord widthTextMax = 0, widthLine,
heightTextTotal = 0, heightLineDefault = 0, heightLine = 0;
wxString curLine;
wxString::const_iterator lineStart = text.begin();
for ( wxString::const_iterator pc = text.begin(); ; ++pc )
{
if ( pc == text.end() || *pc == wxS('\n') )
{
if ( curLine.empty() )
if ( pc == lineStart )
{
// we can't use GetTextExtent - it will return 0 for both width
// and height and an empty line should count in height
@ -137,7 +147,7 @@ void wxTextMeasureBase::GetMultiLineTextExtent(const wxString& text,
}
else
{
CallGetTextExtent(curLine, &widthLine, &heightLine);
CallGetTextExtent(wxString(lineStart, pc), &widthLine, &heightLine);
if ( widthLine > widthTextMax )
widthTextMax = widthLine;
heightTextTotal += heightLine;
@ -149,13 +159,10 @@ void wxTextMeasureBase::GetMultiLineTextExtent(const wxString& text,
}
else // '\n'
{
curLine.clear();
lineStart = pc;
++lineStart;
}
}
else
{
curLine += *pc;
}
}
if ( width )

View File

@ -66,6 +66,7 @@ struct GraphicsBenchmarkOptions
testCircles =
testEllipses =
testTextExtent =
testMultiLineTextExtent =
testPartialTextExtents = false;
usePaint =
@ -95,6 +96,7 @@ struct GraphicsBenchmarkOptions
testCircles,
testEllipses,
testTextExtent,
testMultiLineTextExtent,
testPartialTextExtents;
bool usePaint,
@ -634,7 +636,10 @@ private:
wxStopWatch sw;
for ( long n = 0; n < opts.numIters; n++ )
{
size += dc.GetTextExtent(str);
if ( opts.testMultiLineTextExtent )
size += dc.GetMultiLineTextExtent(str);
else
size += dc.GetTextExtent(str);
}
const long t = sw.Time();
@ -847,6 +852,7 @@ public:
{ wxCMD_LINE_SWITCH, "", "circles" },
{ wxCMD_LINE_SWITCH, "", "ellipses" },
{ wxCMD_LINE_SWITCH, "", "textextent" },
{ wxCMD_LINE_SWITCH, "", "multilinetextextent" },
{ wxCMD_LINE_SWITCH, "", "partialtextextents" },
{ wxCMD_LINE_SWITCH, "", "paint" },
{ wxCMD_LINE_SWITCH, "", "client" },
@ -922,6 +928,7 @@ public:
opts.testCircles = parser.Found("circles");
opts.testEllipses = parser.Found("ellipses");
opts.testTextExtent = parser.Found("textextent");
opts.testMultiLineTextExtent = parser.Found("multilinetextextent");
opts.testPartialTextExtents = parser.Found("partialtextextents");
if ( !(opts.testBitmaps || opts.testImages || opts.testLines
|| opts.testRawBitmaps || opts.testRectangles