【发布时间】:2021-10-07 18:00:21
【问题描述】:
我创建了一个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;
在函数末尾打断点,可以查看LRects中存储的left和right的值。
进入RegionForRange 函数会导致TTextLayoutD2D.DoRegionForRange 但从那里我无法进一步查看可能出现的问题。为什么这些特定字符会发生这种情况并且只发生在这些字体上?为什么范围内的字符后面的字符会影响结果?它是一个错误吗?我或许可以编写一些代码来检测这些序列并纠正位置,但我觉得我不需要这样做。
请注意,我使用的是 Delphi 10.4。我没有尝试更新最近的更新,所以如果有人能确认这个问题发生在哪个版本中,我将不胜感激。
【问题讨论】:
-
您的代码有一个问题。您正在遍历字符串字符,就好像您将拥有基于 0 的字符串,而 Delphi 10.4 默认使用基于 1 的字符串,这意味着第一个字符串字符的索引为 1 而不是 0。
-
@SilverWarior 似乎 TTextRange 对象使用 0 索引,即使 Delphi 中的字符串从索引 1 开始。文档不清楚这一点,但如果我传入 1 作为位置,那么它给出的位置第二个字符。
-
好吧,至少我帮助你纠正了你的循环,使它只产生 2 个循环,而不是像以前那样做 3 个循环。这就是为什么我认为它是通过索引位置读取每个字符串字符的原因。
-
是的,我在回复你之后才意识到。谢谢。
标签: delphi firemonkey delphi-10.4-sydney