首页 > 解决方案 > FMX:为什么 TTextLayout.RegionForRange 在这种特殊情况下会失败?

问题描述

我创建了一个TTextLayout对象,其文本包含连续的“t”字符和“Calibri”字体。然后我有以下代码使用该RegionForRange函数返回每个字符的矩形区域。结果是第一个'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;

在函数的末尾放置一个断点,可以查看存储在 中的 left 和 right 的值LRects

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

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

标签: delphifiremonkeydelphi-10.4-sydney

解决方案


原因被称为连字。应用连字时,两个或多个字形的组合被另一个单个字形替换。

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


推荐阅读