あなたのコードは問題なく動作しているようです。これが私のテストのスクリーンショットです:

なぜあなたの結果が違うのかわかりません。
おそらく私はこれを代替ソリューションとして提供することができます:私は自分自身の正当化方法を書きました:
public void PaintTextJustification(Graphics g, string text, Font font, PointF location, int lineWidth, bool applyToLastLine)
{
  string[] words = text.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
  int wordCount = 0;
  float locY = location.Y;
  while (wordCount < words.Length)
  {
    StringBuilder rawLine = new StringBuilder();
    List<string> lineParts = new List<string>();
    while ((wordCount < words.Length) && (g.MeasureString(rawLine.ToString() + words[wordCount], font).Width < (float)lineWidth))
    {
      rawLine.Append(words[wordCount] + " ");
      lineParts.Add(words[wordCount] + " ");
      wordCount++;
    }
    string rawLineStr = rawLine.ToString().Trim();
    float padding = 0;
    if ((wordCount < words.Length) || (applyToLastLine))
    {
      // Only apply padding if not the last line.
      padding = ((float)lineWidth - g.MeasureString(rawLineStr, font).Width) / (lineParts.Count - 1);
    }
    float locX = location.X;
    foreach (string word in lineParts)
    {
      g.DrawString(word, font, Brushes.Black, new PointF(locX, locY));
      locX += g.MeasureString(word, font).Width + padding;
    }
    locY += g.MeasureString(rawLineStr, font).Height;
  }
}
この新しい方法を使用すると、フォントを選択して行の全長を指定できます。また、柔軟性とカスタマイズ性も向上します(たとえば、最後の行を揃える必要があるかどうかを示すフラグを組み込む)。メソッドの引数としてフォントの色を含めることで、メソッドをさらにカスタマイズすることもできます。
このメソッドは、以下のボタンイベントメソッドに示すように使用できるようになりました(このイベントハンドラーメソッドの最初のビットには、元のソリューションをテストするためのコードが含まれていることに注意してください)。
private void EditButton_Click(object sender, EventArgs e)
{
  IntPtr hdc = richTextBox1.CreateGraphics().GetHdc();
  string str = "aaa bbb ccc ddd eee fff";
  SetTextJustification(hdc, 40, 5);
  TextOut(hdc, 20, 20, str, str.Length);
  SetTextJustification(hdc, 10, 5);
  TextOut(hdc, 20, 40, str, str.Length);
  // Another Approach:
  Graphics g = richTextBox1.CreateGraphics();
  PaintTextJustification(g, str, richTextBox1.Font, new PointF(20f, 90f), 220, true);
  System.Drawing.Font newFont = new Font("Arial", 12f, FontStyle.Bold);
  string longStr = "This is a very long string which will need to be split across several lines when it is justified.";
  PaintTextJustification(g, longStr, newFont, new PointF(20f, 110f), 220, false);
}
これは、両方のアプローチを示す結果のスクリーンショットです。

とにかく、これがお役に立てば幸いです。