-
Notifications
You must be signed in to change notification settings - Fork 806
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix CGPathAddArc and add additional tests. #2136
Conversation
Frameworks/CoreGraphics/CGPath.mm
Outdated
|
||
void SetIsFirstCall(bool firstCall) { | ||
isFirstCall = firstCall; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I very much do not like this mechanism.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to the docs - it is not the "first call", rather the existence of an open sub path - that should be the mechanism used here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also, no test images?
Also, does this allow you to enable @msft-Jeyaram's arc clearing test? |
break; | ||
} | ||
if (moveToPoint == 0) { | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
? needed?
@MSFTFox where are the generated base images for the tests? |
@MSFTFox I've also added some FillMode tests for Arcs. Also depending on who gets the changes in first, arc clearing tests need to be enabled. |
Frameworks/CoreGraphics/CGPath.mm
Outdated
|
||
void SetIsFirstCall(bool firstCall) { | ||
isFirstCall = firstCall; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to the docs - it is not the "first call", rather the existence of an open sub path - that should be the mechanism used here.
void BeginFigure() { | ||
if (!geometrySink->IsFigureOpen()) { | ||
if (geometrySink && !geometrySink->IsFigureOpen()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this logic be in the above function?
Frameworks/CoreGraphics/CGPath.mm
Outdated
@@ -482,6 +486,21 @@ static HRESULT _createPathReadyForFigure(CGPathRef previousPath, | |||
return S_OK; | |||
} | |||
|
|||
static CGFloat __normalizeAngle(CGFloat originalAngle) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A comment explaining what this one is doing would be exceptionally helpful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be useful to add the manual tests to CGCatalog for the primary missing scenario (full circle).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You changed some constant values in the path drawing tests, but didn't update any test images. That worries me.
Additionally, I'm concerned as to why the ArcCircles_NoMove test changed so much...
Frameworks/CoreGraphics/CGPath.mm
Outdated
@@ -567,6 +570,9 @@ void CGPathAddArcToPoint( | |||
|
|||
/** | |||
@Status Interoperable | |||
@Notes For the scenario of drawing a full circle, any distance of 2pi will result in a circle being drawn | |||
regardless of the direction being drawn. The reference platform however, will not draw a circle |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: , however,
(missing preceding comma)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is too wordy, and could be trimmed down to a succinct
All arcs from 0 to 2pi in either direction will result in a circle; the reference platform, by contrast, does not honor this behavior.
Frameworks/CoreGraphics/CGPath.mm
Outdated
return 2 * M_PI; | ||
} | ||
} | ||
if (returnAngle < 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This case should never happen because you're setting it to 0 above if < .00001
Frameworks/CoreGraphics/CGPath.mm
Outdated
// the calculations for arcs since 0, 2pi, 4pi, etc... are all visually the same angle. | ||
static CGFloat __normalizeAngle(CGFloat originalAngle) { | ||
CGFloat returnAngle = fmod(originalAngle, 2 * M_PI); | ||
if (returnAngle < .00001) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
super nit: pull this out into some constant, c_zeroAngleThreshold or something
Frameworks/CoreGraphics/CGPath.mm
Outdated
returnAngle = 0; | ||
} | ||
if (returnAngle == 0) { | ||
if (abs(originalAngle) > 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: this would be more clear as (originalAngle != 0) since you're taking the abs
Frameworks/CoreGraphics/CGPath.mm
Outdated
newSink->AddArc(arcSegment); | ||
// This will only happen when drawing a circle in the clockwise direction from 2pi to 0, a scenario | ||
// supported on the reference platform. | ||
if (abs(abs(rawDifference) - 2 * M_PI) < .00001) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: rawDifference is already abs() from above
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But could still be negative from a counterclockwise rotation. This negative is important later on but the strict value being close enough to zero here is the important factor for when to draw a full circle.
Frameworks/CoreGraphics/CGPath.mm
Outdated
CGFloat normalizedStartAngle = __normalizeAngle(startAngle); | ||
CGFloat normalizedEndAngle = __normalizeAngle(endAngle); | ||
|
||
CGPoint startPoint = CGPointMake(x + radius * cos(normalizedStartAngle), y + radius * sin(normalizedStartAngle)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: you're calculating radius * sin, cos twice
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They're on different angles.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😮 well by golly they are
Frameworks/CoreGraphics/CGPath.mm
Outdated
} | ||
} | ||
if (returnAngle < 0) { | ||
returnAngle += M_PI * 2; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
super super nit: consistent ordering with your (2*pi)s
Frameworks/CoreGraphics/CGPath.mm
Outdated
// This will only happen when drawing a circle in the clockwise direction from 2pi to 0, a scenario | ||
// supported on the reference platform. | ||
if (abs(abs(rawDifference) - 2 * M_PI) < .00001) { | ||
CGFloat midPointAngle = normalizedStartAngle + rawDifference / 2; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: do we wanna just round the latter term to +/- pi here?
Frameworks/CoreGraphics/CGPath.mm
Outdated
CGFloat normalizedStartAngle = __normalizeAngle(startAngle); | ||
CGFloat normalizedEndAngle = __normalizeAngle(endAngle); | ||
|
||
CGPoint startPoint = CGPointMake(x + radius * cos(normalizedStartAngle), y + radius * sin(normalizedStartAngle)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: should this equation be an inline function?
Frameworks/CoreGraphics/CGPath.mm
Outdated
// This function will return a normalized angle in radians between 0 and 2pi. This is to standardize | ||
// the calculations for arcs since 0, 2pi, 4pi, etc... are all visually the same angle. | ||
static CGFloat __normalizeAngle(CGFloat originalAngle) { | ||
CGFloat returnAngle = fmod(originalAngle, 2 * M_PI); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not certain what this function is doing anymore.
Does it boil down to
return std::min(abs(angle), 2 * M_PI);
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not quite, since that would ignore any angle like 7pi/2 and instead return 2 *M_PI. We only want to return an angle of 2pi if the angle is a multiple of 2pi and not 0. That's what the extra checks are for.
@@ -141,10 +141,8 @@ DRAW_TEST_P(CGClearRectArc, ClearArc) { | |||
} | |||
|
|||
static CGPoint sweep[] = { CGPointMake(0, M_PI), CGPointMake(M_PI, 0), CGPointMake(0.3 * M_PI, 0.6 * M_PI), CGPointMake(0, 1.9 * M_PI) }; | |||
// TODO: enable when #2062 is fixed. | |||
INSTANTIATE_TEST_CASE_P(DISABLED_CGContextTests, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
Correctly translates the CoreGraphics arc parameters into D2D1_ARC_SEGMENT parameters. Added additional testing to cover previously known failure situations.
Fix #2062