ご連絡が遅くなりまして申し訳ございません。
また、サンプルプロジェクトもご共有頂きありがとうございます。
> 1.改行位置の計算にスペースを打ち消す計算が考慮されていない
正しいご指摘かと思われます。改行候補の幅は装飾を差し引かない計測結果を用いており、折り返しが早まる可能性があります。
> 2. 自動改行時にスペース打ち消し計算に誤りがある
同一アウトライン幅同士で余計な半分のスペースが入ることは現行コード上は起きないように見受けられます。
1.については、CreateBreakCandidate 内の各スライス計測結果から装飾を差し引くように FTextLayout::CreateBreakCandidate を修正する必要がございます。
FTextLayout::FBreakCandidate FTextLayout::CreateBreakCandidate( int32& OutRunIndex, FLineModel& Line, int32 PreviousBreak, int32 CurrentBreak )
{
//...
if ( BeginIndex == StopIndex )
{
// This slice is empty, no need to adjust anything
SliceSize = SliceSizeWithoutTrailingWhitespace = FVector2D::ZeroVector;
}
else if ( BeginIndex == WhitespaceStopIndex )
{
// This slice contains only whitespace, no need to adjust SliceSizeWithoutTrailingWhitespace
SliceSize = Run.Measure( BeginIndex, StopIndex, Scale, RunTextContext );
//<-------------- Add-Start
// Subtract decoration sizes (shadow/outline) to align wrap measurement with final placement width
const auto ShadowSize = Run.GetRun()->GetShadowSize(BeginIndex, StopIndex, Scale);
const auto OutlineSize = Run.GetRun()->GetOutlineSize(BeginIndex, StopIndex, Scale);
SliceSize.X = FMath::Max(0.0f, SliceSize.X - (ShadowSize.X + OutlineSize.X));
//<-------------- Add-End
SliceSizeWithoutTrailingWhitespace = FVector2D::ZeroVector;
}
else if ( WhitespaceStopIndex != StopIndex )
{
// This slice contains trailing whitespace, measure the text size, then add on the whitespace size
SliceSize = SliceSizeWithoutTrailingWhitespace = Run.Measure( BeginIndex, WhitespaceStopIndex, Scale, RunTextContext );
const float WhitespaceWidth = Run.Measure( WhitespaceStopIndex, StopIndex, Scale, RunTextContext ).X;
SliceSize.X += WhitespaceWidth;
// Subtract decoration sizes for the ranges we measured
//<-------------- Add-Start
// For trimmed width (no trailing whitespace)
const auto ShadowSizeTrimmed = Run.GetRun()->GetShadowSize(BeginIndex, WhitespaceStopIndex, Scale);
const auto OutlineSizeTrimmed = Run.GetRun()->GetOutlineSize(BeginIndex, WhitespaceStopIndex, Scale);
SliceSizeWithoutTrailingWhitespace.X = FMath::Max(0.0f, SliceSizeWithoutTrailingWhitespace.X - (ShadowSizeTrimmed.X + OutlineSizeTrimmed.X));
// For actual size (includes trailing whitespace)
const auto ShadowSizeActual = Run.GetRun()->GetShadowSize(BeginIndex, StopIndex, Scale);
const auto OutlineSizeActual = Run.GetRun()->GetOutlineSize(BeginIndex, StopIndex, Scale);
SliceSize.X = FMath::Max(0.0f, SliceSize.X - (ShadowSizeActual.X + OutlineSizeActual.X));
//<-------------- Add-End
// We also need to measure the width of the first piece of trailing whitespace
if ( WhitespaceStopIndex + 1 == StopIndex )
{
// Only have one piece of whitespace
FirstTrailingWhitespaceCharWidth = WhitespaceWidth;
}
else
{
// Deliberately use the run version of Measure as we don't want the run model to cache this measurement since it may be out of order and break the binary search
FirstTrailingWhitespaceCharWidth = Run.GetRun()->Measure( WhitespaceStopIndex, WhitespaceStopIndex + 1, Scale, RunTextContext ).X;
}
}
else
{
// This slice contains no whitespace, both sizes are the same and can use the same measurement
SliceSize = SliceSizeWithoutTrailingWhitespace = Run.Measure( BeginIndex, StopIndex, Scale, RunTextContext );
// Subtract decoration sizes (shadow/outline)
//<-------------- Add-Start
const auto ShadowSize = Run.GetRun()->GetShadowSize(BeginIndex, StopIndex, Scale);
const auto OutlineSize = Run.GetRun()->GetOutlineSize(BeginIndex, StopIndex, Scale);
const float DecorationX = ShadowSize.X + OutlineSize.X;
SliceSize.X = FMath::Max(0.0f, SliceSize.X - DecorationX);
SliceSizeWithoutTrailingWhitespace.X = FMath::Max(0.0f, SliceSizeWithoutTrailingWhitespace.X - DecorationX);
//<-------------- Add-End
}
修正の前後を比較したものがこちらになりますが、期待するテキスト表示の内容を十分に理解できていたか自信がないため、もし私がご質問の意図を正しく把握できていない箇所がございましたらお知らせください。
[Image Removed]