UCanvas::MeasureStringInternal not taking newline characters into account

Hi UDN,

In UCanvas::MeasureStringInternal, if the current character is ‘\n’, the height of the character is set to the default char height and then the string continues being measured as normal. This means that measuring a string with multiple lines ends up being the same as if it was only one, with the DrawXL parameter becoming larger than expected. I would expect a new line character to cause the following character’s height to be added to “Parameters.DrawYL” and then for the string to continue being measured on a new line.

Is this a bug, or are we misunderstanding how this function should be used?

Thanks,

Bonita

In Canvas.cpp:

for (CurrentPos = BeginPos; CurrentPos < EndPos && *CurrentPos; ++CurrentPos)
{
	float CharWidth, CharHeight;

	const TCHAR Ch = *CurrentPos;
	Parameters.DrawFont->GetCharSize(Ch, CharWidth, CharHeight);
	if (CharHeight == 0 && Ch == TEXT('\n'))
	{
		CharHeight = DefaultCharHeight;
	}

	float CharSpacing = DefaultCharIncrement;
	if (PrevPos)
	{
		CharSpacing += Parameters.DrawFont->GetCharKerning(*PrevPos, Ch) * ScaleX;
	}

	CharWidth *= ScaleX;
	CharHeight *= ScaleY;

	// If we have another character that isn't whitespace, append the character spacing
	const TCHAR* const NextPos = CurrentPos + 1;
	if (NextPos < EndPos && *NextPos && !FChar::IsWhitespace(*NextPos))
	{
		CharWidth += CharSpacing;
	}

	const float ScaledVertSpacing = Parameters.SpacingAdjust.Y * ScaleY;

	Parameters.DrawXL += CharWidth;
	Parameters.DrawYL = FMath::Max<float>(Parameters.DrawYL, CharHeight + ScaledVertSpacing );



Hi Bonita,

It looks to me that this function has been written with the assumption that it won’t have to deal with multiple new lines.

I will double check with the developer who owns this code once he is back from holiday.

As you say we should either add multi line support by incrementing DrawYL or exit out of the iteration when we hit the first newline character to prevent DrawXL becoming an incorrect value.

I’ve noticed that this function is used within Canvas to find the index at which we should wrap text, so it suggests to me that the DrawXL continuing to increment is on oversight which needs fixing and the intention is for this function to be used with a single line at a time.

Thanks for reporting this.

Hi Bonita,

A fix has been submitted to //UE5/Main at CL 45679608 (mirrored to GitHub at 2fbf7c66e08d521148767418621410d57f22b2fc) if you would like to cherry-pick it - otherwise the fix will likely ship in 5.8. There is a minor follow-up change that was also submitted to //UE5/Main at 45680438 (7680b30410ff7261864bd00fb1ca20d78a5f94e1), but this shouldn’t be required.

This logic has been in place since at least 2007, so it’s a bit of an old issue. It should now match string sizing logic elsewhere in the engine, such as in FSlateFontMeasure. FSlateFontMeasure should provide correct results in the case that you’d rather not make engine changes.

Thanks,

Nick