Skip to content

Commit

Permalink
[Controls] Fix wrong size of TSkLabel with AutoSize and Align=None #273
Browse files Browse the repository at this point in the history
Co-Authored-By: Vinícius Felipe Botelho Barbosa <viniciusfbb@users.noreply.github.com>
  • Loading branch information
paulocesarbot and viniciusfbb committed Nov 13, 2023
1 parent 2a45570 commit 7f45095
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 24 deletions.
21 changes: 15 additions & 6 deletions Source/FMX/FMX.Skia.Canvas.pas
Original file line number Diff line number Diff line change
Expand Up @@ -1539,6 +1539,13 @@ TSkRasterCanvas = class(TSkCanvasBase)

{$ENDIF}

function CeilFloat(const X: Single): Single;
begin
Result := Int(X);
if Frac(X) > 0 then
Result := Result + 1;
end;

function GetPixelFormat: TPixelFormat; inline;
begin
{$IF DEFINED(MSWINDOWS)}
Expand Down Expand Up @@ -3164,7 +3171,7 @@ procedure TSkTextLayout.UpdateParagraph;
if WordWrap then
begin
if AMaxLines <= 0 then
Result.MaxLines := High(Integer)
Result.MaxLines := High(NativeUInt)
else
Result.MaxLines := AMaxLines;
end
Expand All @@ -3180,18 +3187,18 @@ procedure TSkTextLayout.UpdateParagraph;
else
Result.TextAlign := SkTextAlign[HorizontalAlign];
Result.TextStyle := CreateDefaultTextStyle;
if Result.MaxLines = NativeUInt(High(Integer)) then
if Result.MaxLines = High(NativeUInt) then
begin
LMinFontSize := Result.TextStyle.FontSize;
for LAttribute in AAttributes do
LMinFontSize := Min(LMinFontSize, LAttribute.Attribute.Font.Size);
if LMinFontSize > 0.1 then
begin
// Avoid invalid float point operation
if MaxSize.Y > High(Integer) then
AMaxLines := High(Integer)
if MaxSize.Y >= High(NativeUInt) then
AMaxLines := High(NativeUInt)
else
AMaxLines := Ceil(MaxSize.Y / LMinFontSize);
AMaxLines := Trunc(CeilFloat(MaxSize.Y / LMinFontSize));
if AMaxLines > 0 then
Result.MaxLines := AMaxLines;
end;
Expand Down Expand Up @@ -3266,7 +3273,9 @@ procedure TSkTextLayout.UpdateParagraph;
if CompareValue(AMaxWidth, 0, TEpsilon.Position) = GreaterThanValue then
begin
// The SkParagraph.Layout calls a floor for the MaxWidth, so we should ceil it to force the original AMaxWidth
AParagraph.Layout(Ceil(AMaxWidth + TEpsilon.Matrix));
if not IsInfinite(AMaxWidth) then
AMaxWidth := CeilFloat(AMaxWidth + TEpsilon.Matrix);
AParagraph.Layout(AMaxWidth);
end
else
AParagraph.Layout(0);
Expand Down
28 changes: 20 additions & 8 deletions Source/FMX/FMX.Skia.pas
Original file line number Diff line number Diff line change
Expand Up @@ -1436,6 +1436,13 @@ function BitmapToSkImage(const ABitmap: TBitmap): ISkImage;
Result := ABitmap.ToSkImage;
end;

function CeilFloat(const X: Single): Single;
begin
Result := Int(X);
if Frac(X) > 0 then
Result := Result + 1;
end;

procedure DrawDesignBorder(const ACanvas: ISkCanvas; ADest: TRectF; const AOpacity: Single);
const
DesignBorderColor = $A0909090;
Expand Down Expand Up @@ -5508,7 +5515,7 @@ procedure TSkLabel.GetFitSize(var AWidth, AHeight: Single);
ParagraphLayout(AWidth);
end
else
ParagraphLayout(High(Integer));
ParagraphLayout(Infinity);
end;
try
AWidth := GetFitWidth;
Expand Down Expand Up @@ -5666,8 +5673,8 @@ function TSkLabel.GetParagraph: ISkParagraph;
Result.TextDirection := TSkTextDirection.RightToLeft;
if ResultingTextSettings.Trimming in [TTextTrimming.Character, TTextTrimming.Word] then
Result.Ellipsis := '...';
if ResultingTextSettings.MaxLines = 0 then
Result.MaxLines := High(Integer)
if ResultingTextSettings.MaxLines <= 0 then
Result.MaxLines := High(NativeUInt)
else
Result.MaxLines := ResultingTextSettings.MaxLines;
Result.TextAlign := SkTextAlign[ResultingTextSettings.HorzAlign];
Expand Down Expand Up @@ -5903,13 +5910,18 @@ function TSkLabel.NormalizeParagraphText(const AText: string): string;

procedure TSkLabel.ParagraphLayout(AMaxWidth: Single);

function DoParagraphLayout(const AParagraph: ISkParagraph; AMaxWidth: Single): Single;
function DoParagraphLayout(const AParagraph: ISkParagraph; const AMaxWidth: Single): Single;
begin
if SameValue(AMaxWidth, 0, TEpsilon.Position) then
Result := AMaxWidth
if CompareValue(AMaxWidth, 0, TEpsilon.Position) = GreaterThanValue then
begin
if IsInfinite(AMaxWidth) then
Result := AMaxWidth
else
// The SkParagraph.Layout calls a floor for the MaxWidth, so we should ceil it to force the original AMaxWidth
Result := CeilFloat(AMaxWidth + TEpsilon.Matrix);
end
else
// The SkParagraph.Layout calls a floor for the MaxWidth, so we should ceil it to force the original AMaxWidth
Result := Ceil(AMaxWidth + TEpsilon.Matrix);
Result := 0;
AParagraph.Layout(Result);
end;

Expand Down
32 changes: 22 additions & 10 deletions Source/VCL/Vcl.Skia.pas
Original file line number Diff line number Diff line change
Expand Up @@ -1354,6 +1354,13 @@ function BitmapToSkImage(const ABitmap: TBitmap): ISkImage;
Result := ABitmap.ToSkImage;
end;

function CeilFloat(const X: Single): Single;
begin
Result := Int(X);
if Frac(X) > 0 then
Result := Result + 1;
end;

procedure CreateBuffer(const AMemDC: HDC; const AWidth, AHeight: Integer;
out ABuffer: HBITMAP; out AData: Pointer; out AStride: Integer);
const
Expand Down Expand Up @@ -5720,15 +5727,15 @@ procedure TSkLabel.GetFitSize(var AWidth, AHeight: Single);
if (akTop in Anchors) and (akBottom in Anchors) then
Result := AHeight
else
Result := Ceil(ParagraphBounds.Height * ScaleFactor);
Result := CeilFloat(ParagraphBounds.Height * ScaleFactor);
end;

function GetFitWidth: Single;
begin
if (akLeft in Anchors) and (akRight in Anchors) then
Result := AWidth
else
Result := Ceil(ParagraphBounds.Width * ScaleFactor);
Result := CeilFloat(ParagraphBounds.Width * ScaleFactor);
end;

var
Expand All @@ -5740,7 +5747,7 @@ procedure TSkLabel.GetFitSize(var AWidth, AHeight: Single);
if (akLeft in Anchors) and (akRight in Anchors) then
ParagraphLayout(AWidth / ScaleFactor)
else
ParagraphLayout(High(Integer));
ParagraphLayout(Infinity);
end;
try
AWidth := GetFitWidth;
Expand Down Expand Up @@ -5864,8 +5871,8 @@ function TSkLabel.GetParagraph: ISkParagraph;
Result.TextDirection := TSkTextDirection.RightToLeft;
if ResultingTextSettings.Trimming in [TSkTextTrimming.Character, TSkTextTrimming.Word] then
Result.Ellipsis := '...';
if ResultingTextSettings.MaxLines = 0 then
Result.MaxLines := High(Integer)
if ResultingTextSettings.MaxLines <= 0 then
Result.MaxLines := High(NativeUInt)
else
Result.MaxLines := ResultingTextSettings.MaxLines;
Result.TextAlign := SkTextAlign[ResultingTextSettings.HorzAlign];
Expand Down Expand Up @@ -6059,13 +6066,18 @@ function TSkLabel.NormalizeParagraphText(const AText: string): string;

procedure TSkLabel.ParagraphLayout(AMaxWidth: Single);

function DoParagraphLayout(const AParagraph: ISkParagraph; AMaxWidth: Single): Single;
function DoParagraphLayout(const AParagraph: ISkParagraph; const AMaxWidth: Single): Single;
begin
if SameValue(AMaxWidth, 0, TEpsilon.Position) then
Result := AMaxWidth
if CompareValue(AMaxWidth, 0, TEpsilon.Position) = GreaterThanValue then
begin
if IsInfinite(AMaxWidth) then
Result := AMaxWidth
else
// The SkParagraph.Layout calls a floor for the MaxWidth, so we should ceil it to force the original AMaxWidth
Result := CeilFloat(AMaxWidth + TEpsilon.Matrix);
end
else
// The SkParagraph.Layout calls a floor for the MaxWidth, so we should ceil it to force the original AMaxWidth
Result := Ceil(AMaxWidth + TEpsilon.Matrix);
Result := 0;
AParagraph.Layout(Result);
end;

Expand Down

0 comments on commit 7f45095

Please sign in to comment.