Skip to content
This repository was archived by the owner on Aug 31, 2021. It is now read-only.

Commit 04cf4af

Browse files
committed
[[ CanvasPathArcTo ]] Add elliptical arc "arc to ... " path command to canvas syntax.
1 parent 9f87b73 commit 04cf4af

File tree

3 files changed

+80
-11
lines changed

3 files changed

+80
-11
lines changed

engine/src/canvas.mlc

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2674,6 +2674,9 @@ public foreign handler MCCanvasPathMoveTo(in pPoint as Point, inout xPath as Pat
26742674
public foreign handler MCCanvasPathLineTo(in pPoint as Point, inout xPath as Path) returns nothing binds to "<builtin>"
26752675
public foreign handler MCCanvasPathCurveThroughPoint(in pThrough as Point, in pTo as Point, inout xPath as Path) returns nothing binds to "<builtin>"
26762676
public foreign handler MCCanvasPathCurveThroughPoints(in pThroughA as Point, in pThroughB as Point, in pTo as Point, inout xPath as Path) returns nothing binds to "<builtin>"
2677+
2678+
public foreign handler MCCanvasPathEllipticArcToWithFlagsWithRadiiAsList(in pTo as Point, in pRadii as List, in pRotation as CanvasFloat, in pLargest as bool, in pClockwise as bool, inout xPath as Path) returns nothing binds to "<builtin>"
2679+
26772680
public foreign handler MCCanvasPathClosePath(inout xPath as Path) returns nothing binds to "<builtin>"
26782681

26792682
/*
@@ -2748,6 +2751,42 @@ begin
27482751
MCCanvasPathCurveThroughPoints(mThroughA, mThroughB, mTo, mPath)
27492752
end syntax
27502753

2754+
2755+
/*
2756+
Summary: Adds an arc to a path.
2757+
2758+
mEnd: An expression which evaluates to a point.
2759+
mRadii: An expression which evaluates to a list of numbers.
2760+
mAngle: An expression which evaluates to a number.
2761+
mPath: An expression which evaluates to a path.
2762+
2763+
Description: Adds an arc from the previous point to <mEnd> on <mPath>, following a section of an ellipse with the given radii & angle.
2764+
As there can be two different ellipses that match the parameters, and two potential arcs for each ellipse, the *largest*, *smallest*, *clockwise*, and *anticlockwise* options allow one arc to specified from the four potential arcs.
2765+
2766+
Example:
2767+
variable tPath
2768+
put the empty path into tPath
2769+
2770+
// Begin a new subpath
2771+
move to point [25, 50] on tPath
2772+
2773+
// Continue path with an arc to 50,25
2774+
arc to point [50, 25] with radii [25, 25] rotated by 0 taking smallest clockwise route on tPath
2775+
2776+
// Begin a new subpath
2777+
move to point [75, 50] on tPath
2778+
// Continue path with a large arc to 50,75
2779+
arc to point [50, 75] with radii [25, 25] rotated by 0 taking largest clockwise route on tPath
2780+
2781+
Tags: Canvas
2782+
*/
2783+
syntax PathOperationEllipticArcToWithFlags is statement
2784+
"arc" "to" <mEnd: Expression> "with" "radii" <mRadii: Expression> "rotated" "by" <mAngle: Expression> "taking" ( "largest" <mLargest=true> | "smallest" <mLargest=false> ) ( "clockwise" <mClockwise=true> | "anticlockwise" <mClockwise=false> ) "route" "on" <mPath: Expression>
2785+
begin
2786+
MCCanvasPathEllipticArcToWithFlagsWithRadiiAsList(mEnd, mRadii, mAngle, mLargest, mClockwise, mPath)
2787+
end syntax
2788+
2789+
27512790
/*
27522791
Summary: Closes the current subpath of a path.
27532792

engine/src/module-canvas.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3690,6 +3690,36 @@ void MCCanvasPathClosePath(MCCanvasPathRef &x_path)
36903690
MCGPathRelease(t_path);
36913691
}
36923692

3693+
void MCCanvasPathEllipticArcToWithFlagsWithRadiiAsList(MCCanvasPointRef p_to, MCProperListRef p_radii, MCCanvasFloat p_rotation, bool p_largest, bool p_clockwise, MCCanvasPathRef &x_path)
3694+
{
3695+
bool t_success;
3696+
t_success = true;
3697+
3698+
MCGPathRef t_path;
3699+
t_path = nil;
3700+
3701+
if (t_success)
3702+
{
3703+
MCGPathMutableCopy(*MCCanvasPathGet(x_path), t_path);
3704+
t_success = MCGPathIsValid(t_path);
3705+
}
3706+
3707+
MCGPoint t_radii;
3708+
if (t_success)
3709+
t_success = MCProperListToRadii(p_radii, t_radii);
3710+
3711+
if (t_success)
3712+
{
3713+
MCGPathArcTo(t_path, MCGSizeMake(t_radii.x, t_radii.y), p_rotation, p_largest, p_clockwise, *MCCanvasPointGet(p_to));
3714+
t_success = MCGPathIsValid(t_path);
3715+
}
3716+
3717+
if (t_success)
3718+
MCCanvasPathSetMCGPath(t_path, x_path);
3719+
3720+
MCGPathRelease(t_path);
3721+
}
3722+
36933723
////////////////////////////////////////////////////////////////////////////////
36943724

36953725
// Effect

libgraphics/src/path.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -776,14 +776,23 @@ static void _MCGPathEllipticArc(MCGPathRef self, const MCGSize &p_radii, MCGFloa
776776

777777
p_angle = fmodf(p_angle + 2 * M_PI, 2 * M_PI);
778778

779+
MCGPoint t_mid;
780+
t_mid = MCGPointGetMidPoint(t_last, p_end_point);
781+
779782
MCGPoint t_p;
780-
t_p = MCGPointRotate(MCGPointMake((t_last.x - p_end_point.x) / 2, (t_last.y - p_end_point.y) / 2), -p_angle);
783+
t_p = MCGPointRotate(MCGPointTranslate(t_last, -t_mid.x, -t_mid.y), -p_angle);
781784

782785
MCGSize t_radii;
783786
t_radii = MCGSizeMake(MCAbs(p_radii.width), MCAbs(p_radii.height));
784787

788+
MCGFloat t_rx2, t_ry2, t_x2, t_y2;
789+
t_rx2 = _sqr(t_radii.width);
790+
t_ry2 = _sqr(t_radii.height);
791+
t_x2 = _sqr(t_p.x);
792+
t_y2 = _sqr(t_p.y);
793+
785794
MCGFloat t_a;
786-
t_a = (_sqr(t_p.x) / _sqr(t_radii.width)) + (_sqr(t_p.y) / _sqr(t_radii.height));
795+
t_a = (t_x2 / t_rx2) + (t_y2 / t_ry2);
787796

788797
MCGPoint t_c;
789798

@@ -797,22 +806,13 @@ static void _MCGPathEllipticArc(MCGPathRef self, const MCGSize &p_radii, MCGFloa
797806
else
798807
{
799808
MCGFloat t_scale;
800-
MCGFloat t_rx2, t_ry2, t_x2, t_y2;
801-
t_rx2 = _sqr(t_radii.width);
802-
t_ry2 = _sqr(t_radii.height);
803-
t_x2 = _sqr(t_p.x);
804-
t_y2 = _sqr(t_p.y);
805-
806809
t_scale = sqrtf((t_rx2 * t_ry2 - t_rx2 * t_y2 - t_ry2 * t_x2) / (t_rx2 * t_y2 + t_ry2 * t_x2));
807810
if (p_large_arc == p_sweep)
808811
t_scale *= -1;
809812

810813
t_c = MCGPointMake(t_scale * t_radii.width * t_p.y / t_radii.height, t_scale * -t_radii.height * t_p.x / t_radii.width);
811814
}
812815

813-
MCGPoint t_mid;
814-
t_mid = MCGPointGetMidPoint(t_last, p_end_point);
815-
816816
MCGPoint t_center;
817817
t_center = MCGPointTranslate(MCGPointRotate(t_c, p_angle), t_mid.x, t_mid.y);
818818

0 commit comments

Comments
 (0)