Skip to content

Try to use FskFont.MeasureText(AText, LRectF, nil); Get incorrect textwidth when a string including unicode emoji. #397

@wqmeng

Description

@wqmeng

Try to use FskFont.MeasureText(AText, LRectF, nil); Get incorrect textwidth when a string including unicode emoji.

Hello,

I try to use FskFont.MeasureText function to get a textwidth, but when the string is '❤Favorite', I get a smaller width of the '❤', My code is

        LTw := FTextMeasurer.TextWidth(FBlockTransName, ACanvas.Font);

        TextRect := TRectF.Create(0, 0, MaxSingle, MaxSingle);
        ACanvas.MeasureText(TextRect, FBlockTransName, False, [], TTextAlign.Leading, TTextAlign.Center);
        LTw := TextRect.Width;

Compare the result with the following ACanvas.MeasureText, the two LTw is different.

In the FTextMeasurer.TextWidth(FBlockTransName, ACanvas.Font); I pass the ACanvas.Font to the FTextMeasurer object function:

function TTextLayoutMeasurer.TextWidth(const AText: string; const AFont: TFont): Single;
var
  LRectF: TRectF;
begin
  FCriticalSection.Enter;
  try
    if AFont <> nil then
    begin
      FOldskFont := FskFont;
      try
        SetFont(AFont);                      // Assign the new font
        FskFont.MeasureText(AText, LRectF, nil);
        Result := LRectF.Width;
        FskFont := FOldskFont;          // Restore the old font
      finally
        FOldskFont  := nil;
      end;
    end
    else begin
      Result := Self.TextWidth(AText);
    end;
  finally
    FCriticalSection.Leave;
  end;
end;

In the SetFont function, I create a skFont from the AFont, then use FskFont.MeasureText(AText, LRectF, nil); to get the width of the string,

procedure TTextLayoutMeasurer.SetFont(const AFont: TFont);
var
  LBold, LItalic: Boolean;
begin
  if AFont <> nil then begin
//    if TPlatformServices.Current.SupportsPlatformService(IFMXSystemFontService,  IInterface(LFMXFontService)) then begin
//      LFontName := LFMXFontService.GetDefaultFontFamilyName;
//    end else begin
//      LFontName := 'Arial';
//    end;
    FTypeface := nil;

    LBold := false;
    LItalic := false;
    if TFontStyle.fsBold in AFont.Style then
      LBold := True;
    if TFontStyle.fsItalic in AFont.Style then
      LItalic := True;

    if LBold and LItalic then begin
      FTypeface := TSkTypeface.MakeFromName(AFont.Family, tskFontStyle.BoldItalic);
    end else if LBold then begin
      FTypeface := TSkTypeface.MakeFromName(AFont.Family, tskFontStyle.Bold)
    end else if LItalic then begin
      FTypeface := TSkTypeface.MakeFromName(AFont.Family, tskFontStyle.Italic)
    end else begin
      FTypeface := TSkTypeface.MakeFromName(AFont.Family, tskFontStyle.Normal);
    end;

    if FTypeface <> nil then begin
      if FskFont <> nil then
        FskFont := nil;
      FskFont := TSkFont.Create(FTypeface, AFont.Size, 1);
      FskFont.Edging := TSkFontEdging.AntiAlias;
    end;
    FCanvasFontSetted := True;
  end;
end;

Am I missing something?

Thank you.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions