LCL/Graphics: Fix win32 widgetset Arc method overload with angle arguments to behave like in all other widgetsets. Issue #41748.

This commit is contained in:
wp_xyz 2025-07-11 00:42:00 +02:00
parent bd717d60cb
commit 7b9621f234
2 changed files with 43 additions and 1 deletions

View File

@ -72,6 +72,9 @@ function Distance(const Pt, SP, EP : TFloatPoint) : Extended; overload;
function EccentricAngle(const PT : TPoint; const Rect : TRect) : Extended;
procedure EllipseParams2Coords(X, Y, Width, Height: Integer;
Angle1, Angle2: Integer; var SX, SY, EX, EY: Integer);
function EllipseRadialLength(const Rect : TRect; EccentricAngle : Extended) : Longint;
function EllipsePolygon(const aRect: TRect): TPointArray;
@ -340,6 +343,41 @@ begin
EY := EP.Y;
end;
{-------------------------------------------------------------------------------
Method: EllipseParams2Coords
Params: x, y, width, height, angle1, angle2, sx, sy, ex, ey
Returns: Nothing
In parametric form, the ellipse equation for every point (x, y) along the
perimeter is
x = a * cos (t), y = b * sin(t)
where a and b are the major and minor half-axes of the ellipse, and t is
an "angle" parameter ranging between 0 and 2*pi.
This procedure used by the Windows Arc method calculates the start and end
points, (SX, SY) and (EX, EY), respectively, of an arc beginning at
parameter t = angle1 and ending at parameter t = angle1 + angle2.
But note that angle1 and angle2 are expressed as multiples of 1/16 degree.
Positive values of the angles are in counter-clockwise, negative values in
clockwise direction.
Zero degrees is at 3'o clock position.
-------------------------------------------------------------------------------}
procedure EllipseParams2Coords(X, Y, Width, Height: Integer;
Angle1, Angle2: Integer; var SX, SY, EX, EY: Integer);
var
sinAngle1, cosAngle1, sinAngle2, cosAngle2: Extended;
a, b: Integer;
begin
SinCos(DegToRad(Angle1/16), sinAngle1, cosAngle1);
SinCos(DegToRad((Angle1 + Angle2)/16), sinAngle2, cosAngle2);
a := Width div 2;
b := Height div 2;
SX := X + a + round(cosAngle1 * a);
SY := Y + b - round(sinAngle1 * b);
EX := X + a + round(cosAngle2 * a);
EY := Y + b - round(sinAngle2 * b);
end;
{------------------------------------------------------------------------------
Method: Arc2Bezier
Params: X, Y, Width, Height, Angle1, Angle2, Rotation, Points, Count

View File

@ -46,6 +46,10 @@
circle equals 5760 (16*360). Positive values of Angle and AngleLength mean
counter-clockwise while negative values mean clockwise direction.
Zero degrees is at the 3'o clock position.
But note that due to the elliptic eccetricity these angles are not the
same as "real" polar angles, but only correspond to the parameter t in the
ellipse equations: x = a * cos(t); y = b * sin(t)
------------------------------------------------------------------------------}
function TWin32WidgetSet.Arc(DC: HDC; Left, Top, Right, Bottom, Angle16Deg, Angle16DegLength: Integer): Boolean;
var
@ -58,7 +62,7 @@ begin
if Angle16DegLength < 0 then OldArcDirection := Windows.SetArcDirection(DC, AD_CLOCKWISE)
else OldArcDirection := Windows.SetArcDirection(DC, AD_COUNTERCLOCKWISE);
Angles2Coords(Left, Top, Right - Left, Bottom - Top, Angle16Deg, Angle16DegLength, SX, SY, EX, EY);
EllipseParam2Coords(Left, Top, Right - Left, Bottom - Top, Angle16Deg, Angle16DegLength, SX, SY, EX, EY);
Result := Boolean(Windows.Arc(DC, Left, Top, Right, Bottom, SX, SY, EX, EY));
// Revert the arc direction to the previous value
Windows.SetArcDirection(DC, OldArcDirection);