Is it a bug ? TextWidth('Hello') + TextWidth('World') TextWidth('HelloWorld');

Is it a bug ? TextWidth('Hello') + TextWidth('World') <> TextWidth('HelloWorld');

in a FMX application under Windows with an Italic font

procedure TForm1.FormPaint(Sender: TObject; Canvas: TCanvas;
const ARect: TRectF);
var
TextLayout: TTextLayout;
w1, w2, w3: Single;
begin
TextLayout := TTextLayoutManager.DefaultTextLayout.Create(Canvas);
TextLayout.Font.Family := 'Arial';
TextLayout.Font.Style := [TFontStyle.fsItalic];
TextLayout.Text := 'Hello';
w1 := TextLayout.TextWidth;
TextLayout.Text := 'World';
w2 := TextLayout.TextWidth;
TextLayout.Text := 'HelloWorld';
w3 := TextLayout.TextWidth;
TextLayout.Free;

Memo1.Lines.Add('TextWidth(Hello) = ' + FloatToStrF(w1, TFloatFormat.ffFixed, 15, 2));
Memo1.Lines.Add('TextWidth(World) = ' + FloatToStrF(w2, TFloatFormat.ffFixed, 15, 2));
Memo1.Lines.Add('TextWidth(HelloWord) = ' + FloatToStrF(w3, TFloatFormat.ffFixed, 15, 2));
Memo1.Lines.Add('TextWidth(Hello) + TextWidth(Word) = ' + FloatToStrF(w1 + w2, TFloatFormat.ffFixed, 15, 2));
{
TextWidth(Hello) = 29,06
TextWidth(World) = 33,17
TextWidth(HelloWord) = 60,52
TextWidth(Hello) + TextWidth(Word) = 62,23
}
end;

Comments

  1. is the W overlapping the o? Than the calculation is correct. Give it a Try with LOL and OLO to see what happens

    ReplyDelete
  2. under VCL I don't have this problem

    procedure TForm2.FormPaint(Sender: TObject);
    var
    w1, w2, w3: Integer;
    begin
    Canvas.Font.Name := 'Arial';
    Canvas.Font.Style := [fsItalic];
    w1 := Canvas.TextWidth('Hello');
    w2 := Canvas.TextWidth('World');
    w3 := Canvas.TextWidth('HelloWorld');

    Memo1.Lines.Add('TextWidth(Hello) = ' + IntToStr(w1));
    Memo1.Lines.Add('TextWidth(World) = ' + IntToStr(w2));
    Memo1.Lines.Add('TextWidth(HelloWord) = ' + IntToStr(w3));
    Memo1.Lines.Add('TextWidth(Hello) + TextWidth(Word) = ' + IntToStr(w1 + w2));
    {
    TextWidth(Hello) = 26
    TextWidth(World) = 30
    TextWidth(HelloWord) = 56
    TextWidth(Hello) + TextWidth(Word) = 56
    }
    end;

    ReplyDelete
  3. Probably because VCL uses GDI and FMX uses DirectX?

    ReplyDelete
  4. Okay but how can I draw a selected text if I can't know the real selected portion width ?!
    github.com - Delphi

    ReplyDelete
  5. Text rendering can often change spacing between characters, because a font is often tweaked for specific pairs, font sizes, etc. If you want to see something really cool, look up ligatures, where pairs of characters are actually replaced with single symbols.

    In terms of drawing a selection, if you want to select "Wor" in "HelloWorld", finding the text width of "Hello" and "Wor" should do the trick well enough for a selection.

    ReplyDelete
  6. ok, I've found what is to be done

    1) use TextLayout.AddAttribute() to specify fonts change in the string
    2) use TextLayout.RegionForRange returns the selected portion rectangle where I need to draw the selection background
    3) TextLayout.RenderLayout display the text with the specified attributes

    ReplyDelete

Post a Comment