FMX:为什么 TTextLayout.RegionForRange 在这种特殊情况下会失败?

FMX: Why does TTextLayout.RegionForRange fail in this particular case?

我创建了一个 TTextLayout 对象,其文本包含连续的 't' 个字符和 'Calibri' 字体。然后,我使用 RegionForRange 函数将以下代码 return 每个字符的矩形区域。结果是第一个't'的宽度为0,第二个't'的位置和第一个一样。文本中的任何其他字符都是正确的 - 即使是错误之后的字符,尽管字母 'f' 和 't' 和 'f' 的任何连续组合也有同样的问题。大多数其他字体似乎不会导致问题,尽管 'Gabriola' 会。

procedure TForm1.FormCreate(Sender: TObject);
var
  Layout : TTextLayout;
  LRange : TTextRange;
  LRegion : TRegion;
  LRects : array of TRectF;
  i : Integer;
begin
  Layout := TTextLayoutManager.DefaultTextLayout.Create;
  Layout.Font.Size := 20;
  // Calibra and Gabriola fail but Arial and most other fonts don't
  Layout.Font.Family := 'Calibri';// 'Gabriola';
  Layout.Text := 'tt'; // ff, ft, tf also fail

  LRange.Length := 1;
  SetLength(LRects, Length(Layout.Text));
  for i := 0 to Length(Layout.Text) - 1 do begin
    LRange.Pos := i;
    LRegion := Layout.RegionForRange(LRange);
    LRects[i] := LRegion[0]; // Bounding rect of this character
  end;

end;

在函数末尾打个断点,可以看到LRects.

中存储的left和right的值

进入 RegionForRange 函数会导致 TTextLayoutD2D.DoRegionForRange 但从那里我无法进一步查看可能出了什么问题。为什么这会发生在这些特定字符上,而且只发生在这些字体上?为什么范围内字符后面的字符会影响结果?这是一个错误吗?我也许可以编写一些代码来检测这些序列并更正位置,但我觉得我不需要这样做。

请注意,我使用的是 Delphi 10.4。我没有尝试过最近的更新,所以如果有人能确认这个问题发生在哪个版本中,我将不胜感激。

原因叫做ligature。 应用连字时,两个或多个字形的组合将被另一个单个字形替换。

连字由 OpenType 字体定义。每种字体都定义了自己的一组连字。 Calibri 定义了很多(你只找到了几个)。