Search code examples
delphifiremonkeydelphi-10.4-sydney

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


I have created a TTextLayout object with text containing consecutive 't' characters and with the 'Calibri' font. I then have the following code to return the rectangular region of each character using the RegionForRange function. The result is that the width of the 1st 't' is 0 and the position of the 2nd 't' is the same as the first. Any other characters in the text are correct - even ones after the error, although the letter 'f' also has the same problem and any consecutive combination of 't' and 'f'. Most other fonts don't seem to cause the problem, although 'Gabriola' does.

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;

Put a break point at the end of the function to see the values of left and right stored in LRects.

Stepping into the RegionForRange function leads to TTextLayoutD2D.DoRegionForRange but from there I can't go any further to see what could be going wrong. Why could this be happening for these particular characters and only for these fonts? Why should the character following the one in the range affect the result? Is it a bug? I could perhaps write some code to detect these sequences and correct the position, but I don't feel that I should need to do that.

Note that I'm using Delphi 10.4. I have not tried more recent updates, so I would appreciate if someone could confirm that this issue occurs and in which version.


Solution

  • The reason is called ligature. When a ligature is applied, a combination of two or more glyphs is replaced by another, single glyph.

    Ligatures are defined by OpenType fonts. Each font defines its own set of ligatures. Calibri defines a lot (you have found only a few ones).