Skip to content
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

Merged
merged 10 commits into from
Mar 9, 2017

Conversation

MSFTFox
Copy link
Member

@MSFTFox MSFTFox commented Mar 2, 2017

Correctly translates the CoreGraphics arc parameters into D2D1_ARC_SEGMENT parameters. Added additional testing to cover previously known failure situations.

Fix #2062


void SetIsFirstCall(bool firstCall) {
isFirstCall = firstCall;
}

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.

Copy link
Contributor

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.

Copy link

@DHowett-MSFT DHowett-MSFT left a 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?

@DHowett-MSFT
Copy link

Also, does this allow you to enable @msft-Jeyaram's arc clearing test?

break;
}
if (moveToPoint == 0) {
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

? needed?

@msft-Jeyaram
Copy link
Contributor

msft-Jeyaram commented Mar 2, 2017

@MSFTFox where are the generated base images for the tests?
I think it got missed in your addition

@msft-Jeyaram
Copy link
Contributor

@MSFTFox I've also added some FillMode tests for Arcs.
These were parameterized tests that I've added to ensure arcs was working.
Please enable them when #2133 is in.
There is a TODO with issue id #2062

Also depending on who gets the changes in first, arc clearing tests need to be enabled.
The disabled tests are tagged with the Arc issue ids.


void SetIsFirstCall(bool firstCall) {
isFirstCall = firstCall;
}
Copy link
Contributor

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()) {

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?

@@ -482,6 +486,21 @@ static HRESULT _createPathReadyForFigure(CGPathRef previousPath,
return S_OK;
}

static CGFloat __normalizeAngle(CGFloat originalAngle) {

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.

Copy link
Contributor

@rajsesh rajsesh left a 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).

Copy link

@DHowett-MSFT DHowett-MSFT left a 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...

@@ -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

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)

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.

return 2 * M_PI;
}
}
if (returnAngle < 0) {
Copy link
Contributor

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

// 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) {
Copy link
Contributor

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

returnAngle = 0;
}
if (returnAngle == 0) {
if (abs(originalAngle) > 0) {
Copy link
Contributor

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

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) {
Copy link
Contributor

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

Copy link
Member Author

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.

CGFloat normalizedStartAngle = __normalizeAngle(startAngle);
CGFloat normalizedEndAngle = __normalizeAngle(endAngle);

CGPoint startPoint = CGPointMake(x + radius * cos(normalizedStartAngle), y + radius * sin(normalizedStartAngle));
Copy link
Contributor

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

Copy link
Member Author

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.

Copy link
Contributor

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

}
}
if (returnAngle < 0) {
returnAngle += M_PI * 2;
Copy link
Contributor

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

// 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;
Copy link
Contributor

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?

CGFloat normalizedStartAngle = __normalizeAngle(startAngle);
CGFloat normalizedEndAngle = __normalizeAngle(endAngle);

CGPoint startPoint = CGPointMake(x + radius * cos(normalizedStartAngle), y + radius * sin(normalizedStartAngle));
Copy link
Contributor

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?

// 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);

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);

?

Copy link
Member Author

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,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@MSFTFox MSFTFox merged commit a974bc3 into microsoft:develop Mar 9, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants