From 5e19ec85de431b2ff97d64146ae0e820efe5b3d2 Mon Sep 17 00:00:00 2001 From: Hank Fox Date: Tue, 1 Nov 2016 16:18:33 -0700 Subject: [PATCH 1/8] Implement arcs and curves in CGPath using D2D --- Frameworks/CoreGraphics/CGPath.mm | 344 ++++++++++-------- Frameworks/CoreGraphics/D2DWrapper.mm | 1 - .../CGCatalog-Headers.vcxitems | 6 +- .../CGCatalog-Headers.vcxitems.filters | 10 +- .../CGCatalog-WinStore10/CGCatalog.vcxproj | 4 + .../CGCatalog.vcxproj.filters | 18 + .../CGCatalog.xcodeproj/project.pbxproj | 20 + .../testapps/CGCatalog/CGCatalog/CGDrawView.m | 2 + .../CGPathAddArcToPointViewController.h | 24 ++ .../CGPathAddArcToPointViewController.m | 61 ++++ .../CGCatalog/CGPathAddArcViewController.h | 24 ++ .../CGCatalog/CGPathAddArcViewController.m | 76 ++++ .../CGCatalog/CGCatalog/Resources/AddArc.png | 3 + .../CGCatalog/Resources/AddArcToPoint.png | 3 + .../CGCatalog/Resources/AddCurveToPoint.png | 4 +- .../CGCatalog/Resources/AddElipseToRect.png | 4 +- .../CGCatalog/Resources/AddLineToPoint.png | 4 +- .../CGCatalog/CGCatalog/Resources/AddPath.png | 4 +- .../Resources/AddQuadCurveToPoint.png | 4 +- .../CGCatalog/Resources/CloseSubPath.png | 4 +- .../CGCatalog/Resources/GetBoundingBox.png | 4 +- .../CGCatalog/Resources/PathAddRect.png | 4 +- .../CGCatalog/Resources/PathApply.png | 4 +- .../Samples/CGContextNewTestsController.m | 12 +- tests/unittests/CoreGraphics/CGPathTests.mm | 53 ++- 25 files changed, 505 insertions(+), 192 deletions(-) create mode 100644 tests/testapps/CGCatalog/CGCatalog/CGPathAddArcToPointViewController.h create mode 100644 tests/testapps/CGCatalog/CGCatalog/CGPathAddArcToPointViewController.m create mode 100644 tests/testapps/CGCatalog/CGCatalog/CGPathAddArcViewController.h create mode 100644 tests/testapps/CGCatalog/CGCatalog/CGPathAddArcViewController.m create mode 100644 tests/testapps/CGCatalog/CGCatalog/Resources/AddArc.png create mode 100644 tests/testapps/CGCatalog/CGCatalog/Resources/AddArcToPoint.png diff --git a/Frameworks/CoreGraphics/CGPath.mm b/Frameworks/CoreGraphics/CGPath.mm index 3ef609721f..d6e429368e 100644 --- a/Frameworks/CoreGraphics/CGPath.mm +++ b/Frameworks/CoreGraphics/CGPath.mm @@ -65,6 +65,14 @@ inline CGPoint __CreateCGPointWithTransform(CGFloat x, CGFloat y, const CGAffine return geometrySink; } + void SetPathGeometry(ComPtr path) { + pathGeometry = path; + } + + void SetGeometrySink(ComPtr sink) { + geometrySink = sink; + } + CGPoint GetCurrentPoint() { return currentPoint; } @@ -248,120 +256,67 @@ void CGPathAddLineToPoint(CGMutablePathRef path, const CGAffineTransform* transf path->SetCurrentPoint(pt); } -CGFloat _CGPathControlPointOffsetMultiplier(CGFloat angle) { - // Constant used to approximate circles with bezier curves. - // An n-piece cubic Bezier curve can approximate a circle, - // when each inner control point is the distance 4/3 * tan(t/4) - // from an outer control point on a unit circle, where t is 360/n degrees, and - // n > 2 - return (4.0f / 3.0f) * tan(angle / 4.0f); -} - /** - @Status Caveat - @Notes transform property not supported + @Status Interoperable */ void CGPathAddArcToPoint( CGMutablePathRef path, const CGAffineTransform* transform, CGFloat x1, CGFloat y1, CGFloat x2, CGFloat y2, CGFloat radius) { - bool isEmpty = CGPathIsEmpty(path); + RETURN_IF(!path); - if (isEmpty) { - return; - } + CGPoint curPathPosition = path->GetCurrentPoint(); - CGPoint curPathPosition = CGPathGetCurrentPoint(path); - double x0, y0; - double dx0, dy0, dx2, dy2, xl0, xl2; - double san, n0x, n0y, n2x, n2y, t; + CGPoint tangentPoint1 = __CreateCGPointWithTransform(x1, y1, transform); + CGPoint tangentPoint2 = __CreateCGPointWithTransform(x2, y2, transform); - x0 = curPathPosition.x; - y0 = curPathPosition.y; + x1 = tangentPoint1.x; + y1 = tangentPoint1.y; - dx0 = x0 - x1; - dy0 = y0 - y1; - xl0 = sqrt(dx0 * dx0 + dy0 * dy0); - if (xl0 == 0) - return; + x2 = tangentPoint2.x; + y2 = tangentPoint2.y; - dx2 = x2 - x1; - dy2 = y2 - y1; - xl2 = sqrt(dx2 * dx2 + dy2 * dy2); + CGFloat dx1 = x1 - curPathPosition.x; + CGFloat dy1 = y1 - curPathPosition.y; - san = dx2 * dy0 - dx0 * dy2; - if (san == 0) { - CGPathAddLineToPoint(path, transform, x1, y1); - return; + CGFloat dx2 = x1 - x2; + CGFloat dy2 = y1 - y2; + + // Normalize the angles we're working with. + CGFloat startAngle = fmod(atan2(dy1, dx1), 2 * M_PI); + CGFloat endAngle = fmod(atan2(dy2, dx2), 2 * M_PI); + if (startAngle < 0) { + startAngle += M_PI * 2; + } + if (endAngle < 0) { + endAngle += M_PI * 2; } - if (san < 0) { - n0x = -dy0 / xl0; - n0y = dx0 / xl0; - n2x = dy2 / xl2; - n2y = -dx2 / xl2; - } else { - n0x = dy0 / xl0; - n0y = -dx0 / xl0; - n2x = -dy2 / xl2; - n2y = dx2 / xl2; - } - t = (dx2 * n2y - dx2 * n0y - dy2 * n2x + dy2 * n0x) / san; - CGPathAddArc(path, - transform, - (CGFloat)(x1 + radius * (t * dx0 + n0x)), - (CGFloat)(y1 + radius * (t * dy0 + n0y)), - radius, - (CGFloat)atan2(-n0y, -n0x), - (CGFloat)atan2(-n2y, -n2x), - (san < 0)); -} - -// Internal function to break down Arcs into pieces smaller than pi/2. -void _CGPathAddArc(CGMutablePathRef path, - const CGAffineTransform* transform, - CGFloat x, - CGFloat y, - CGFloat radius, - CGFloat startAngle, - CGFloat endAngle, - bool clockwise) { - // Get the difference between the start and end angle for this arc - CGFloat delta = endAngle - startAngle; - - // If the difference is larger than pi/2 then this arc needs to be - // broken down into more pieces - // .00001f is used instead of epsilon here to avoid infinite loops with - // values close to pi/2 - if ((fabs(delta) > M_PI_2) && (fabs((M_PI_2 - fabs(delta))) > 0.00001f)) { - // Calculate the angle in the middle of the start & end angle. - CGFloat midAngle = startAngle + (M_PI_2 * (delta < 0 ? -1.0f : 1.0f)); - - // Call this function again now with the smaller arcs - _CGPathAddArc(path, transform, x, y, radius, startAngle, midAngle, clockwise); - _CGPathAddArc(path, transform, x, y, radius, midAngle, endAngle, clockwise); - return; - } - - // The start and end points for the arc, not yet adjusted with the center of - // the arc - CGPoint arcStartRelative = CGPointMake((cos(startAngle) * radius), (sin(startAngle) * radius)); - CGPoint arcEndRelative = CGPointMake((cos(endAngle) * radius), (sin(endAngle) * radius)); - - // The start and end points of the arc, adjuste for the center. - CGPoint arcStart = CGPointMake(arcStartRelative.x + x, arcStartRelative.y + y); - CGPoint arcEnd = CGPointMake(arcEndRelative.x + x, arcEndRelative.y + y); - - // Use the angle size to determine the offset for control points - CGFloat offsetMultiplier = _CGPathControlPointOffsetMultiplier(delta); - - // Create the curve with the control points properly offset - CGPathAddCurveToPoint(path, - transform, - arcStart.x - (offsetMultiplier * arcStartRelative.y), - arcStart.y + (offsetMultiplier * arcStartRelative.x), - arcEnd.x + (offsetMultiplier * arcEndRelative.y), - arcEnd.y - (offsetMultiplier * arcEndRelative.x), - arcEnd.x, - arcEnd.y); + CGFloat bisector = (endAngle - startAngle) / 2; + + // tanLength is the distance to the point on the circle from the tangent line. + CGFloat tanLength = abs(radius / tan(bisector)); + + CGFloat tanPointAx = x1 - (tanLength * cos(startAngle)); + CGFloat tanPointAy = y1 - (tanLength * sin(startAngle)); + CGFloat tanPointBx = x1 - (tanLength * cos(endAngle)); + CGFloat tanPointBy = y1 - (tanLength * sin(endAngle)); + + CGPoint endPoint = CGPointMake(tanPointBx, tanPointBy); + const D2D1_POINT_2F endPointD2D = _CGPointToD2D_F(CGPointMake(tanPointBx, tanPointBy)); + + D2D1_SWEEP_DIRECTION sweepDirection = { startAngle + M_PI < endAngle ? D2D1_SWEEP_DIRECTION_CLOCKWISE : + D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE }; + const D2D1_SIZE_F radiusD2D = { radius, radius }; + FLOAT rotationAngle = bisector * 2; + D2D1_ARC_SIZE arcSize = D2D1_ARC_SIZE_SMALL; + D2D1_ARC_SEGMENT arcSegment = D2D1::ArcSegment(endPointD2D, radiusD2D, rotationAngle, sweepDirection, arcSize); + + // Append a line to the point we need to begin drawing the arc from. + FAIL_FAST_IF_FAILED(path->PreparePathForEditing()); + path->BeginFigure(); + CGPathAddLineToPoint(path, transform, tanPointAx, tanPointAy); + + path->GetGeometrySink()->AddArc(arcSegment); + path->SetCurrentPoint(endPoint); } /** @@ -377,38 +332,36 @@ void CGPathAddArc(CGMutablePathRef path, bool clockwise) { RETURN_IF(!path); - // Normalize the start angle so it's between 0 and 2*pi - startAngle = fmod(startAngle, 2.0f * M_PI); - if (startAngle < 0.0f) { - startAngle += 2.0f * M_PI; - } + CGPoint startPoint = __CreateCGPointWithTransform(x + radius * cos(startAngle), y + radius * sin(startAngle), transform); + CGPoint endPoint = __CreateCGPointWithTransform(x + radius * cos(endAngle), y + radius * sin(endAngle), transform); - // Normalize the end angle so it's between 0 and 2*pi - endAngle = fmod(endAngle, 2.0f * M_PI); - if (endAngle < 0.0f) { - endAngle += 2.0f * M_PI; + if (!CGPointEqualToPoint(path->GetCurrentPoint(), startPoint)) { + CGPathAddLineToPoint(path, nullptr, startPoint.x, startPoint.y); } - // Calculate the starting point of the arc - CGPoint arcStart = CGPointMake((cos(startAngle) * radius) + x, (sin(startAngle) * radius) + y); - - // Either draw a line to or move to the start of the arc - if (!CGPathIsEmpty(path)) { - CGPathAddLineToPoint(path, transform, arcStart.x, arcStart.y); + // Create the parameters for the AddArc method. + const D2D1_POINT_2F endPointD2D = _CGPointToD2D_F(endPoint); + const D2D1_SIZE_F radiusD2D = { radius, radius }; + CGFloat rotationAngle = abs(startAngle - endAngle); + D2D1_ARC_SIZE arcSize = D2D1_ARC_SIZE_SMALL; + CGFloat expectedAngle = (clockwise ? startAngle + rotationAngle : startAngle - rotationAngle); + + // D2D does not understand that the ending angle must be pointing in the proper direction, thus we must translate + // what it means to have an ending angle to the proper small arc or large arc that D2D will use since a circle will + // intersect that point regardless of which direction it is drawn in. + if (expectedAngle == endAngle) { + arcSize = D2D1_ARC_SIZE_LARGE; } else { - CGPathMoveToPoint(path, transform, arcStart.x, arcStart.y); + rotationAngle = (2 * M_PI) - rotationAngle; } + D2D1_SWEEP_DIRECTION sweepDirection = { clockwise ? D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE : D2D1_SWEEP_DIRECTION_CLOCKWISE }; + D2D1_ARC_SEGMENT arcSegment = D2D1::ArcSegment(endPointD2D, radiusD2D, rotationAngle, sweepDirection, arcSize); - // Adjust the start/endangles to force the arc - // to be pieced together clockwise or counter-clockwise - if (clockwise && endAngle > startAngle) { - startAngle += 2.0f * M_PI; - } else if (!clockwise && startAngle > endAngle) { - endAngle += 2.0f * M_PI; - } + FAIL_FAST_IF_FAILED(path->PreparePathForEditing()); + path->BeginFigure(); + path->GetGeometrySink()->AddArc(arcSegment); - // Call the internal function for breaking the arcs down into smaller segments - _CGPathAddArc(path, transform, x, y, radius, startAngle, endAngle, clockwise); + path->SetCurrentPoint(endPoint); } /** @@ -460,8 +413,12 @@ void CGPathAddPath(CGMutablePathRef path, const CGAffineTransform* transform, CG // Close the path we're adding and open the path we need to add to. FAIL_FAST_IF_FAILED(toAdd->ClosePath()); + FAIL_FAST_IF_FAILED(path->PreparePathForEditing()); + path->EndFigure(D2D1_FIGURE_END_OPEN); FAIL_FAST_IF_FAILED(toAdd->GetPathGeometry()->Stream(path->GetGeometrySink().Get())); + path->SetCurrentPoint(toAdd->GetCurrentPoint()); + path->SetStartingPoint(toAdd->GetStartingPoint()); } /** @@ -469,31 +426,40 @@ void CGPathAddPath(CGMutablePathRef path, const CGAffineTransform* transform, CG */ void CGPathAddEllipseInRect(CGMutablePathRef path, const CGAffineTransform* transform, CGRect rect) { RETURN_IF(!path); + CGRect containingRectangle = rect; + // First we must transform the coordinates of the rectangle if necessary. + if (transform) { + containingRectangle = CGRectApplyAffineTransform(rect, *transform); + } - // Determine the control point offset multiplier to create 4 arcs - CGFloat offsetMultiplier = _CGPathControlPointOffsetMultiplier(M_PI_2); + CGFloat radiusX = containingRectangle.size.width / 2.0; + CGFloat radiusY = containingRectangle.size.height / 2.0; + CGPoint center = CGPointMake(containingRectangle.origin.x + radiusX, containingRectangle.origin.y + radiusY); - CGFloat xControlPointOffset = offsetMultiplier * CGRectGetWidth(rect) / 2.0; - CGFloat yControlPointOffset = offsetMultiplier * CGRectGetHeight(rect) / 2.0; + D2D1_ELLIPSE ellipse = D2D1::Ellipse(_CGPointToD2D_F(center), radiusX, radiusY); - CGFloat minX = CGRectGetMinX(rect); - CGFloat midX = CGRectGetMidX(rect); - CGFloat maxX = CGRectGetMaxX(rect); + ComPtr factory; + FAIL_FAST_IF_FAILED(_CGGetD2DFactory(&factory)); + ComPtr ellipseGeometry; - CGFloat minY = CGRectGetMinY(rect); - CGFloat midY = CGRectGetMidY(rect); - CGFloat maxY = CGRectGetMaxY(rect); + FAIL_FAST_IF_FAILED(factory->CreateEllipseGeometry(&ellipse, &ellipseGeometry)); - // Move to the center of the ellipse - CGPathMoveToPoint(path, transform, maxX, midY); + path->ClosePath(); - // Add the 4 curves for the ellipse - CGPathAddCurveToPoint(path, transform, maxX, midY + yControlPointOffset, midX + xControlPointOffset, maxY, midX, maxY); - CGPathAddCurveToPoint(path, transform, midX - xControlPointOffset, maxY, minX, midY + yControlPointOffset, minX, midY); - CGPathAddCurveToPoint(path, transform, minX, midY - yControlPointOffset, midX - xControlPointOffset, minY, midX, minY); - CGPathAddCurveToPoint(path, transform, midX + xControlPointOffset, minY, maxX, midY - yControlPointOffset, maxX, midY); + // Create temp vars for new path/sink + ComPtr newPath; + ComPtr newSink; - CGPathCloseSubpath(path); + // Open a new path that the contents of the old path will be streamed into. We cannot re-use the same path as it is now closed + // and cannot be opened again. We use the newPath variable because the factory was returning the same pointer for some strange + // reason so this will force it to do otherwise. + FAIL_FAST_IF_FAILED(factory->CreatePathGeometry(&newPath)); + FAIL_FAST_IF_FAILED(newPath->Open(&newSink)); + + FAIL_FAST_IF_FAILED(ellipseGeometry->CombineWithGeometry(path->GetPathGeometry().Get(), D2D1_COMBINE_MODE_XOR, NULL, newSink.Get())); + + path->SetPathGeometry(newPath); + path->SetGeometrySink(newSink); } /** @@ -503,13 +469,15 @@ void CGPathCloseSubpath(CGMutablePathRef path) { RETURN_IF(!path); // Move the current point to the starting point since the line is closed. - path->SetCurrentPoint(path->GetStartingPoint()); - path->EndFigure(D2D1_FIGURE_END_CLOSED); + // path->SetCurrentPoint(path->GetStartingPoint()); + if (!CGPointEqualToPoint(path->GetStartingPoint(), path->GetCurrentPoint())) { + CGPathAddLineToPoint(path, nullptr, path->GetStartingPoint().x, path->GetStartingPoint().y); + } + path->EndFigure(D2D1_FIGURE_END_OPEN); // CLOSED); } /** -@Status Stub -@Notes +@Status Interoperable */ CGRect CGPathGetBoundingBox(CGPathRef path) { if (path == NULL) { @@ -566,16 +534,23 @@ CGPathRef CGPathRetain(CGPathRef path) { } /** -@Status Stub -@Notes +@Status Interoperable */ void CGPathAddQuadCurveToPoint(CGMutablePathRef path, const CGAffineTransform* transform, CGFloat cpx, CGFloat cpy, CGFloat x, CGFloat y) { - UNIMPLEMENTED(); + RETURN_IF(!path); + + CGPoint endPoint = __CreateCGPointWithTransform(x, y, transform); + CGPoint controlPoint = __CreateCGPointWithTransform(cpx, cpy, transform); + + FAIL_FAST_IF_FAILED(path->PreparePathForEditing()); + path->BeginFigure(); + path->GetGeometrySink()->AddQuadraticBezier(D2D1::QuadraticBezierSegment(_CGPointToD2D_F(controlPoint), _CGPointToD2D_F(endPoint))); + + path->SetCurrentPoint(endPoint); } /** -@Status Stub -@Notes +@Status Interoperable */ void CGPathAddCurveToPoint(CGMutablePathRef path, const CGAffineTransform* transform, @@ -585,7 +560,18 @@ void CGPathAddCurveToPoint(CGMutablePathRef path, CGFloat cp2y, CGFloat x, CGFloat y) { - UNIMPLEMENTED(); + RETURN_IF(!path); + + CGPoint endPoint = __CreateCGPointWithTransform(x, y, transform); + CGPoint controlPoint1 = __CreateCGPointWithTransform(cp1x, cp1y, transform); + CGPoint controlPoint2 = __CreateCGPointWithTransform(cp2x, cp2y, transform); + + FAIL_FAST_IF_FAILED(path->PreparePathForEditing()); + path->BeginFigure(); + path->GetGeometrySink()->AddBezier( + D2D1::BezierSegment(_CGPointToD2D_F(controlPoint1), _CGPointToD2D_F(controlPoint2), _CGPointToD2D_F(endPoint))); + + path->SetCurrentPoint(endPoint); } /** @@ -633,13 +619,49 @@ void CGPathAddRelativeArc( UNIMPLEMENTED(); } +static inline D2D_RECT_F __CGRectToD2D_F(CGRect rect) { + return { + rect.origin.x, rect.origin.y, rect.origin.x + rect.size.width, rect.origin.y + rect.size.height, + }; +} + /** - @Status Stub + @Status Interoperable @Notes */ void CGPathAddRoundedRect( CGMutablePathRef path, const CGAffineTransform* transform, CGRect rect, CGFloat cornerWidth, CGFloat cornerHeight) { - UNIMPLEMENTED(); + RETURN_IF(!path); + + // First we must transform the coordinates of the rectangle if necessary. + if (transform) { + rect = CGRectApplyAffineTransform(rect, *transform); + } + + D2D1_RECT_F rectangle = __CGRectToD2D_F(rect); + D2D1_ROUNDED_RECT roundedRectangle = { rectangle, cornerWidth, cornerHeight }; + + ComPtr factory; + FAIL_FAST_IF_FAILED(_CGGetD2DFactory(&factory)); + ComPtr rectangleGeometry; + + FAIL_FAST_IF_FAILED(factory->CreateRoundedRectangleGeometry(&roundedRectangle, &rectangleGeometry)); + + path->ClosePath(); + + // Create temp vars for new path/sink + ComPtr newPath; + ComPtr newSink; + + // Open a new path that the contents of the old path will be streamed into. We cannot re-use the same path as it is now closed + // and cannot be opened again. + FAIL_FAST_IF_FAILED(factory->CreatePathGeometry(&newPath)); + FAIL_FAST_IF_FAILED(newPath->Open(&newSink)); + + FAIL_FAST_IF_FAILED(rectangleGeometry->CombineWithGeometry(path->GetPathGeometry().Get(), D2D1_COMBINE_MODE_XOR, NULL, newSink.Get())); + + path->SetPathGeometry(newPath); + path->SetGeometrySink(newSink); } int _CGPathPointCountForElementType(CGPathElementType type) { @@ -728,12 +750,14 @@ CGMutablePathRef CGPathCreateMutableCopyByTransformingPath(CGPathRef path, const } /** - @Status Stub + @Status Interoperable @Notes */ CGPathRef CGPathCreateWithRoundedRect(CGRect rect, CGFloat cornerWidth, CGFloat cornerHeight, const CGAffineTransform* transform) { - UNIMPLEMENTED(); - return StubReturn(); + CGMutablePathRef ret = CGPathCreateMutable(); + CGPathAddRoundedRect(ret, transform, rect, cornerWidth, cornerHeight); + + return (CGPathRef)ret; } /** diff --git a/Frameworks/CoreGraphics/D2DWrapper.mm b/Frameworks/CoreGraphics/D2DWrapper.mm index eea735e5bd..4ba23766d0 100644 --- a/Frameworks/CoreGraphics/D2DWrapper.mm +++ b/Frameworks/CoreGraphics/D2DWrapper.mm @@ -22,7 +22,6 @@ HRESULT _CGGetD2DFactory(ID2D1Factory** factory) { static ComPtr sFactory; static HRESULT sHr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, __uuidof(ID2D1Factory), &sFactory); - sFactory.CopyTo(factory); RETURN_HR(sHr); } diff --git a/tests/testapps/CGCatalog/CGCatalog.vsimporter/CGCatalog-Headers-WinStore10/CGCatalog-Headers.vcxitems b/tests/testapps/CGCatalog/CGCatalog.vsimporter/CGCatalog-Headers-WinStore10/CGCatalog-Headers.vcxitems index 2238a6ce49..aeb452f183 100644 --- a/tests/testapps/CGCatalog/CGCatalog.vsimporter/CGCatalog-Headers-WinStore10/CGCatalog-Headers.vcxitems +++ b/tests/testapps/CGCatalog/CGCatalog.vsimporter/CGCatalog-Headers-WinStore10/CGCatalog-Headers.vcxitems @@ -1,4 +1,4 @@ - + true @@ -9,6 +9,8 @@ {1A3847F4-5684-4B1C-8AAA-24A80180D8D6} + + @@ -40,4 +42,4 @@ - + \ No newline at end of file diff --git a/tests/testapps/CGCatalog/CGCatalog.vsimporter/CGCatalog-Headers-WinStore10/CGCatalog-Headers.vcxitems.filters b/tests/testapps/CGCatalog/CGCatalog.vsimporter/CGCatalog-Headers-WinStore10/CGCatalog-Headers.vcxitems.filters index 740f8723c8..eae9baf05e 100644 --- a/tests/testapps/CGCatalog/CGCatalog.vsimporter/CGCatalog-Headers-WinStore10/CGCatalog-Headers.vcxitems.filters +++ b/tests/testapps/CGCatalog/CGCatalog.vsimporter/CGCatalog-Headers-WinStore10/CGCatalog-Headers.vcxitems.filters @@ -1,4 +1,4 @@ - + @@ -93,5 +93,11 @@ CGCatalog\OldSamples + + CGCatalog\NewSamples + + + CGCatalog\NewSamples + - + \ No newline at end of file diff --git a/tests/testapps/CGCatalog/CGCatalog.vsimporter/CGCatalog-WinStore10/CGCatalog.vcxproj b/tests/testapps/CGCatalog/CGCatalog.vsimporter/CGCatalog-WinStore10/CGCatalog.vcxproj index 1d8d2e1a0e..2f64bbe473 100644 --- a/tests/testapps/CGCatalog/CGCatalog.vsimporter/CGCatalog-WinStore10/CGCatalog.vcxproj +++ b/tests/testapps/CGCatalog/CGCatalog.vsimporter/CGCatalog-WinStore10/CGCatalog.vcxproj @@ -179,6 +179,8 @@ + + @@ -188,6 +190,8 @@ + + diff --git a/tests/testapps/CGCatalog/CGCatalog.vsimporter/CGCatalog-WinStore10/CGCatalog.vcxproj.filters b/tests/testapps/CGCatalog/CGCatalog.vsimporter/CGCatalog-WinStore10/CGCatalog.vcxproj.filters index 97daceaeb5..b851c38d90 100644 --- a/tests/testapps/CGCatalog/CGCatalog.vsimporter/CGCatalog-WinStore10/CGCatalog.vcxproj.filters +++ b/tests/testapps/CGCatalog/CGCatalog.vsimporter/CGCatalog-WinStore10/CGCatalog.vcxproj.filters @@ -196,10 +196,28 @@ + + + + CGCatalog\NewSamples + + CGCatalog\NewSamples + + + CGCatalog\NewSamples + + + + + CGCatalog\Resources + + + CGCatalog\Resources + \ No newline at end of file diff --git a/tests/testapps/CGCatalog/CGCatalog.xcodeproj/project.pbxproj b/tests/testapps/CGCatalog/CGCatalog.xcodeproj/project.pbxproj index 610f0c2d90..610d857d6d 100644 --- a/tests/testapps/CGCatalog/CGCatalog.xcodeproj/project.pbxproj +++ b/tests/testapps/CGCatalog/CGCatalog.xcodeproj/project.pbxproj @@ -11,6 +11,10 @@ 552816081D062F6B0082C178 /* CGCCGContextViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 552816071D062F6B0082C178 /* CGCCGContextViewController.m */; }; 5528160A1D0630300082C178 /* LogoAutodesk.png in Resources */ = {isa = PBXBuildFile; fileRef = 552816091D0630300082C178 /* LogoAutodesk.png */; }; 5579D6771D1B73EC00B33059 /* CGCCGPathContainsPointViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5579D6761D1B73EC00B33059 /* CGCCGPathContainsPointViewController.m */; }; + 8B2360531DC92A90008F4EBF /* CGPathAddArcViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B2360521DC92A90008F4EBF /* CGPathAddArcViewController.m */; }; + 8B2360561DD690CC008F4EBF /* CGPathAddArcToPointViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B2360551DD690CC008F4EBF /* CGPathAddArcToPointViewController.m */; }; + 8B2360591DDAACAE008F4EBF /* AddArc.png in Resources */ = {isa = PBXBuildFile; fileRef = 8B2360571DDAACAE008F4EBF /* AddArc.png */; }; + 8B23605A1DDAACAE008F4EBF /* AddArcToPoint.png in Resources */ = {isa = PBXBuildFile; fileRef = 8B2360581DDAACAE008F4EBF /* AddArcToPoint.png */; }; 8B2D2E821D9DA57700B8E557 /* AddCurveToPoint.png in Resources */ = {isa = PBXBuildFile; fileRef = 8B2D2E7D1D9DA57700B8E557 /* AddCurveToPoint.png */; }; 8B2D2E831D9DA57700B8E557 /* AddElipseToRect.png in Resources */ = {isa = PBXBuildFile; fileRef = 8B2D2E7E1D9DA57700B8E557 /* AddElipseToRect.png */; }; 8B2D2E841D9DA57700B8E557 /* AddLineToPoint.png in Resources */ = {isa = PBXBuildFile; fileRef = 8B2D2E7F1D9DA57700B8E557 /* AddLineToPoint.png */; }; @@ -59,6 +63,12 @@ 552816091D0630300082C178 /* LogoAutodesk.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = LogoAutodesk.png; sourceTree = ""; }; 5579D6751D1B73EC00B33059 /* CGCCGPathContainsPointViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGCCGPathContainsPointViewController.h; sourceTree = ""; }; 5579D6761D1B73EC00B33059 /* CGCCGPathContainsPointViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CGCCGPathContainsPointViewController.m; sourceTree = ""; }; + 8B2360511DC92A90008F4EBF /* CGPathAddArcViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGPathAddArcViewController.h; sourceTree = ""; }; + 8B2360521DC92A90008F4EBF /* CGPathAddArcViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CGPathAddArcViewController.m; sourceTree = ""; }; + 8B2360541DD690CC008F4EBF /* CGPathAddArcToPointViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGPathAddArcToPointViewController.h; sourceTree = ""; }; + 8B2360551DD690CC008F4EBF /* CGPathAddArcToPointViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CGPathAddArcToPointViewController.m; sourceTree = ""; }; + 8B2360571DDAACAE008F4EBF /* AddArc.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AddArc.png; sourceTree = ""; }; + 8B2360581DDAACAE008F4EBF /* AddArcToPoint.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AddArcToPoint.png; sourceTree = ""; }; 8B2D2E7D1D9DA57700B8E557 /* AddCurveToPoint.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AddCurveToPoint.png; sourceTree = ""; }; 8B2D2E7E1D9DA57700B8E557 /* AddElipseToRect.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AddElipseToRect.png; sourceTree = ""; }; 8B2D2E7F1D9DA57700B8E557 /* AddLineToPoint.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AddLineToPoint.png; sourceTree = ""; }; @@ -140,6 +150,10 @@ 8BC8830E1D90A33F009115D0 /* NewSamples */ = { isa = PBXGroup; children = ( + 8B2360541DD690CC008F4EBF /* CGPathAddArcToPointViewController.h */, + 8B2360551DD690CC008F4EBF /* CGPathAddArcToPointViewController.m */, + 8B2360511DC92A90008F4EBF /* CGPathAddArcViewController.h */, + 8B2360521DC92A90008F4EBF /* CGPathAddArcViewController.m */, 8BF7B3DC1D9C63FA00C25A86 /* CGPathAddCurveToPointViewController.h */, 8BF7B3DD1D9C63FA00C25A86 /* CGPathAddCurveToPointViewController.m */, 8BF7B3DE1D9C63FA00C25A86 /* CGPathAddElipseViewController.h */, @@ -246,6 +260,8 @@ F0D21CB81D0605E1002C32EE /* Resources */ = { isa = PBXGroup; children = ( + 8B2360571DDAACAE008F4EBF /* AddArc.png */, + 8B2360581DDAACAE008F4EBF /* AddArcToPoint.png */, 8B2D2E8F1D9DA5F100B8E557 /* CloseSubPath.png */, 8B2D2E901D9DA5F100B8E557 /* GetBoundingBox.png */, 8B2D2E8B1D9DA5C800B8E557 /* CloseSubPath.png */, @@ -322,6 +338,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 8B23605A1DDAACAE008F4EBF /* AddArcToPoint.png in Resources */, 8B2D2E841D9DA57700B8E557 /* AddLineToPoint.png in Resources */, 8B2D2E8A1D9DA5A000B8E557 /* PathApply.png in Resources */, 8B2D2E831D9DA57700B8E557 /* AddElipseToRect.png in Resources */, @@ -331,6 +348,7 @@ 8B2D2E851D9DA57700B8E557 /* AddPath.png in Resources */, 5528160A1D0630300082C178 /* LogoAutodesk.png in Resources */, F0D21CBC1D0605ED002C32EE /* Launch Screen.storyboard in Resources */, + 8B2360591DDAACAE008F4EBF /* AddArc.png in Resources */, 8B2D2E8E1D9DA5C800B8E557 /* GetBoundingBox.png in Resources */, 8B2D2E891D9DA5A000B8E557 /* PathAddRect.png in Resources */, F0D21CBA1D0605E1002C32EE /* Assets.xcassets in Resources */, @@ -352,6 +370,7 @@ 8B9D65101D89C42800153CCF /* CGContextNewTestsController.m in Sources */, F0D21C891D05FEF9002C32EE /* CGCRootViewController.m in Sources */, 8BF7B3F01D9C63FA00C25A86 /* CGPathAddCurveToPointViewController.m in Sources */, + 8B2360531DC92A90008F4EBF /* CGPathAddArcViewController.m in Sources */, FBA3A50C1D132C9A00C3C011 /* CGCCGContextReplacePathWithStrokedPath.m in Sources */, 8BF7B3F21D9C63FA00C25A86 /* CGPathAddLineToPointViewController.m in Sources */, 8B6186D31D89CD1800DA47F4 /* CGContextSamplesRootViewController.m in Sources */, @@ -363,6 +382,7 @@ 552816081D062F6B0082C178 /* CGCCGContextViewController.m in Sources */, 8BF7B3F81D9C63FA00C25A86 /* CGPathContainsPointViewController.m in Sources */, 5579D6771D1B73EC00B33059 /* CGCCGPathContainsPointViewController.m in Sources */, + 8B2360561DD690CC008F4EBF /* CGPathAddArcToPointViewController.m in Sources */, F0D21C861D05FEF9002C32EE /* AppDelegate.m in Sources */, 8B9D65131D89C5EB00153CCF /* CGContextSampleRow.m in Sources */, F0D21CBF1D06078D002C32EE /* CGCBaseViewController.m in Sources */, diff --git a/tests/testapps/CGCatalog/CGCatalog/CGDrawView.m b/tests/testapps/CGCatalog/CGCatalog/CGDrawView.m index e4c54d6223..ed61b04a0a 100644 --- a/tests/testapps/CGCatalog/CGCatalog/CGDrawView.m +++ b/tests/testapps/CGCatalog/CGCatalog/CGDrawView.m @@ -23,6 +23,7 @@ @implementation CGDrawView { - (id)initWithFrame:(CGRect)rect drawOptions:(CGDrawOptions*)options { if (self = [super initWithFrame:rect]) { _options = options; + [self setBackgroundColor:[UIColor whiteColor]]; } return self; } @@ -32,6 +33,7 @@ - (void)setDrawBlock:(void (^)(void))block { } - (void)drawRect:(CGRect)rect { + [super drawRect:rect]; if (drawBlock) { drawBlock(); } diff --git a/tests/testapps/CGCatalog/CGCatalog/CGPathAddArcToPointViewController.h b/tests/testapps/CGCatalog/CGCatalog/CGPathAddArcToPointViewController.h new file mode 100644 index 0000000000..ab63ed8775 --- /dev/null +++ b/tests/testapps/CGCatalog/CGCatalog/CGPathAddArcToPointViewController.h @@ -0,0 +1,24 @@ +//****************************************************************************** +// +// Copyright (c) Microsoft. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +//****************************************************************************** + +#pragma once + +#import "CGCBaseViewController.h" +#import +#import "CGSamplePage.h" + +@interface CGPathAddArcToPointViewController : CGCBaseViewController +@end diff --git a/tests/testapps/CGCatalog/CGCatalog/CGPathAddArcToPointViewController.m b/tests/testapps/CGCatalog/CGCatalog/CGPathAddArcToPointViewController.m new file mode 100644 index 0000000000..30672b47bf --- /dev/null +++ b/tests/testapps/CGCatalog/CGCatalog/CGPathAddArcToPointViewController.m @@ -0,0 +1,61 @@ +//****************************************************************************** +// +// Copyright (c) Microsoft. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +//****************************************************************************** + +#import "CGPathAddArcToPointViewController.h" +#import "CGDrawView.h" + +@implementation CGPathAddArcToPointViewController + +- (id)initWithDrawingOptions:(CGDrawOptions*)options { + self = [super initWithDrawingOptions:options]; + return self; +} + +- (void)loadView { + [super loadView]; + [self.view setBackgroundColor:[UIColor clearColor]]; + + CGDrawView* drawView = [[CGDrawView alloc] initWithFrame:self.view.bounds drawOptions:self.options]; + [drawView setDrawBlock:^(void) { + CGContextRef currentContext = UIGraphicsGetCurrentContext(); + + CGContextSetLineWidth(currentContext, self.options.lineWidth); + CGContextSetStrokeColorWithColor(currentContext, self.options.lineColor); + CGContextSetLineDash(currentContext, self.options.linePhase, self.options.lineDashPattern, self.options.lineDashCount); + + CGMutablePathRef thepath = CGPathCreateMutable(); + CGPathMoveToPoint(thepath, NULL, 75, 100); + CGPathAddArcToPoint(thepath, NULL, 50, 150, 100, 250, 15); + CGPathAddArcToPoint(thepath, NULL, 100, 250, 150, 150, 15); + CGPathAddArcToPoint(thepath, NULL, 150, 150, 100, 50, 15); + CGPathAddArcToPoint(thepath, NULL, 100, 50, 50, 150, 15); + CGPathAddLineToPoint(thepath, NULL, 75, 100); + + CGContextAddPath(currentContext, thepath); + + CGContextStrokePath(currentContext); + + CGPathRelease(thepath); + + [super drawComparisonCGImageFromImageName:@"AddArcToPoint" intoContext:currentContext]; + }]; + + [self.view addSubview:drawView]; + + [super addComparisonLabel]; +} + +@end diff --git a/tests/testapps/CGCatalog/CGCatalog/CGPathAddArcViewController.h b/tests/testapps/CGCatalog/CGCatalog/CGPathAddArcViewController.h new file mode 100644 index 0000000000..5562459aba --- /dev/null +++ b/tests/testapps/CGCatalog/CGCatalog/CGPathAddArcViewController.h @@ -0,0 +1,24 @@ +//****************************************************************************** +// +// Copyright (c) Microsoft. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +//****************************************************************************** + +#pragma once + +#import "CGCBaseViewController.h" +#import +#import "CGSamplePage.h" + +@interface CGPathAddArcViewController : CGCBaseViewController +@end diff --git a/tests/testapps/CGCatalog/CGCatalog/CGPathAddArcViewController.m b/tests/testapps/CGCatalog/CGCatalog/CGPathAddArcViewController.m new file mode 100644 index 0000000000..8e09e0c04d --- /dev/null +++ b/tests/testapps/CGCatalog/CGCatalog/CGPathAddArcViewController.m @@ -0,0 +1,76 @@ +//****************************************************************************** +// +// Copyright (c) Microsoft. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +//****************************************************************************** + +#import "CGPathAddArcViewController.h" +#import "CGDrawView.h" + +@implementation CGPathAddArcViewController + +- (id)initWithDrawingOptions:(CGDrawOptions*)options { + self = [super initWithDrawingOptions:options]; + return self; +} + +- (void)loadView { + [super loadView]; + [self.view setBackgroundColor:[UIColor clearColor]]; + + CGDrawView* drawView = [[CGDrawView alloc] initWithFrame:self.view.bounds drawOptions:self.options]; + [drawView setDrawBlock:^(void) { + CGContextRef currentContext = UIGraphicsGetCurrentContext(); + + CGContextSetLineWidth(currentContext, self.options.lineWidth); + CGContextSetStrokeColorWithColor(currentContext, self.options.lineColor); + CGContextSetLineDash(currentContext, self.options.linePhase, self.options.lineDashPattern, self.options.lineDashCount); + + CGMutablePathRef thepath = CGPathCreateMutable(); + CGPathMoveToPoint(thepath, NULL, 100, 100); + CGPathAddArc(thepath, NULL, 100, 100, 75, 0, M_PI / 2, true); + CGPathCloseSubpath(thepath); + + CGPathMoveToPoint(thepath, NULL, 110, 90); + CGPathAddArc(thepath, NULL, 110, 90, 75, M_PI / 2, 0, true); + CGPathCloseSubpath(thepath); + + CGPathMoveToPoint(thepath, NULL, 400, 150); + CGPathAddArc(thepath, NULL, 300, 150, 100, 0, M_PI / 2, true); + CGPathAddArc(thepath, NULL, 300, 150, 100, M_PI / 2, 0, true); + CGPathMoveToPoint(thepath, NULL, 200, 150); + CGPathAddArc(thepath, NULL, 250, 150, 50, M_PI, 0, false); + CGPathMoveToPoint(thepath, NULL, 300, 150); + CGPathAddArc(thepath, NULL, 350, 150, 50, M_PI, 0, true); + CGPathMoveToPoint(thepath, NULL, 275, 150); + CGPathAddArc(thepath, NULL, 250, 150, 25, 0, M_PI / 2, true); + CGPathAddArc(thepath, NULL, 250, 150, 25, M_PI / 2, 0, true); + CGPathMoveToPoint(thepath, NULL, 375, 150); + CGPathAddArc(thepath, NULL, 350, 150, 25, 0, M_PI / 2, true); + CGPathAddArc(thepath, NULL, 350, 150, 25, M_PI / 2, 0, true); + + CGContextAddPath(currentContext, thepath); + + CGContextStrokePath(currentContext); + + CGPathRelease(thepath); + + [super drawComparisonCGImageFromImageName:@"AddArc" intoContext:currentContext]; + }]; + + [self.view addSubview:drawView]; + + [super addComparisonLabel]; +} + +@end diff --git a/tests/testapps/CGCatalog/CGCatalog/Resources/AddArc.png b/tests/testapps/CGCatalog/CGCatalog/Resources/AddArc.png new file mode 100644 index 0000000000..b7cd0cfbe1 --- /dev/null +++ b/tests/testapps/CGCatalog/CGCatalog/Resources/AddArc.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:85514f88340bc8614645f860be99633b1a4cfd44cc863ff58420f950f254d252 +size 16224 diff --git a/tests/testapps/CGCatalog/CGCatalog/Resources/AddArcToPoint.png b/tests/testapps/CGCatalog/CGCatalog/Resources/AddArcToPoint.png new file mode 100644 index 0000000000..56c88bcfda --- /dev/null +++ b/tests/testapps/CGCatalog/CGCatalog/Resources/AddArcToPoint.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7a96e9a85bfb30309b50279d4b5591f481e7284471582c7194f5cfe167cc3538 +size 6890 diff --git a/tests/testapps/CGCatalog/CGCatalog/Resources/AddCurveToPoint.png b/tests/testapps/CGCatalog/CGCatalog/Resources/AddCurveToPoint.png index bb32babe45..cf7fb20c70 100644 --- a/tests/testapps/CGCatalog/CGCatalog/Resources/AddCurveToPoint.png +++ b/tests/testapps/CGCatalog/CGCatalog/Resources/AddCurveToPoint.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bba843e972479efa1d2fe73610ba20dc4951efb3745d4f85ae2f208ddb6a5bbc -size 4585 +oid sha256:7bf945f07beb25942c6e37e60b2fbe135b1028d7459b91368d347f3fab92002a +size 4360 diff --git a/tests/testapps/CGCatalog/CGCatalog/Resources/AddElipseToRect.png b/tests/testapps/CGCatalog/CGCatalog/Resources/AddElipseToRect.png index 05cc1d701e..7705fc1c32 100644 --- a/tests/testapps/CGCatalog/CGCatalog/Resources/AddElipseToRect.png +++ b/tests/testapps/CGCatalog/CGCatalog/Resources/AddElipseToRect.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f3a7957ff2077a4ad29f3e503b797808c62874c8b1f39cc513e365b45e4c326e -size 9008 +oid sha256:9769a33bddecb26f23caca15a51be512d6fdb5ab7cea5ed63cccbb9379ce4788 +size 10350 diff --git a/tests/testapps/CGCatalog/CGCatalog/Resources/AddLineToPoint.png b/tests/testapps/CGCatalog/CGCatalog/Resources/AddLineToPoint.png index e5f6be64c3..5d4349ffa0 100644 --- a/tests/testapps/CGCatalog/CGCatalog/Resources/AddLineToPoint.png +++ b/tests/testapps/CGCatalog/CGCatalog/Resources/AddLineToPoint.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b742d86b4e9c92c28a929e7446d19a74b5898b39c137553fa6f3e8ea18cca386 -size 6835 +oid sha256:e0a1c81a70d9f45147a75392be0e03a7a5fe4433b91b6af0129368952337081e +size 8354 diff --git a/tests/testapps/CGCatalog/CGCatalog/Resources/AddPath.png b/tests/testapps/CGCatalog/CGCatalog/Resources/AddPath.png index 3728bd1121..e569ddd8f2 100644 --- a/tests/testapps/CGCatalog/CGCatalog/Resources/AddPath.png +++ b/tests/testapps/CGCatalog/CGCatalog/Resources/AddPath.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:09942a4e25fd4422db0b245c5f539bccc3dc7823c7ecb0d8efd27f76a44352a2 -size 8016 +oid sha256:17e0e8a25272e5bd00c232ee6ad54f1be5e79a9f267c47ddb47a92008075c539 +size 9402 diff --git a/tests/testapps/CGCatalog/CGCatalog/Resources/AddQuadCurveToPoint.png b/tests/testapps/CGCatalog/CGCatalog/Resources/AddQuadCurveToPoint.png index 6680b12a70..da7d5a824b 100644 --- a/tests/testapps/CGCatalog/CGCatalog/Resources/AddQuadCurveToPoint.png +++ b/tests/testapps/CGCatalog/CGCatalog/Resources/AddQuadCurveToPoint.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2b7e670313375832ede6a4aa3d983e98c0f5da82c2170f606604873b1fd8a2cf -size 6144 +oid sha256:b0c315617e54f6a973cd9a0ab297fc7fd52fbf9e217c5f768e89d4142f33b54b +size 7200 diff --git a/tests/testapps/CGCatalog/CGCatalog/Resources/CloseSubPath.png b/tests/testapps/CGCatalog/CGCatalog/Resources/CloseSubPath.png index ad38b9db9e..fcbfc23708 100644 --- a/tests/testapps/CGCatalog/CGCatalog/Resources/CloseSubPath.png +++ b/tests/testapps/CGCatalog/CGCatalog/Resources/CloseSubPath.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5a698f557fdbd83b129a02d07c33af9abf9c583635097fcc1293502a7da1c5db -size 4700 +oid sha256:33cdec89b6c489d995a3390350f7876971fcd4bf3dd2397ea4d77b06f660417d +size 5827 diff --git a/tests/testapps/CGCatalog/CGCatalog/Resources/GetBoundingBox.png b/tests/testapps/CGCatalog/CGCatalog/Resources/GetBoundingBox.png index 3ee6016ba4..14be29cd47 100644 --- a/tests/testapps/CGCatalog/CGCatalog/Resources/GetBoundingBox.png +++ b/tests/testapps/CGCatalog/CGCatalog/Resources/GetBoundingBox.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8f4b485d2b988c44530c36b1f9e8e10e7aa702430766fba229bc263f1752f210 -size 6918 +oid sha256:2d13da988c22f128c46b117381f108de59748391c00c8fd33f99808aab4df848 +size 8348 diff --git a/tests/testapps/CGCatalog/CGCatalog/Resources/PathAddRect.png b/tests/testapps/CGCatalog/CGCatalog/Resources/PathAddRect.png index 210b968234..5ff3f08cb9 100644 --- a/tests/testapps/CGCatalog/CGCatalog/Resources/PathAddRect.png +++ b/tests/testapps/CGCatalog/CGCatalog/Resources/PathAddRect.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:af075d1faefca56694b230673e475b71553f729d4b5490ae147106551a01a511 -size 4254 +oid sha256:5128cec44e5850a60a598dc5ae4d0635ea3318cab75aa1d89910cade71431375 +size 5000 diff --git a/tests/testapps/CGCatalog/CGCatalog/Resources/PathApply.png b/tests/testapps/CGCatalog/CGCatalog/Resources/PathApply.png index fb9344a865..58b4a79a91 100644 --- a/tests/testapps/CGCatalog/CGCatalog/Resources/PathApply.png +++ b/tests/testapps/CGCatalog/CGCatalog/Resources/PathApply.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:49b65d34a515dc14098e378ee4e2561b3680559895781b1c1683397900644c37 -size 8915 +oid sha256:8ae58e10af03384eaec9e822f0c017fe827d833f3f5876e736af6f58e9753555 +size 10528 diff --git a/tests/testapps/CGCatalog/CGCatalog/Samples/CGContextNewTestsController.m b/tests/testapps/CGCatalog/CGCatalog/Samples/CGContextNewTestsController.m index 47dd43986b..114d219d5d 100644 --- a/tests/testapps/CGCatalog/CGCatalog/Samples/CGContextNewTestsController.m +++ b/tests/testapps/CGCatalog/CGCatalog/Samples/CGContextNewTestsController.m @@ -29,6 +29,8 @@ #import "CGPathCloseSubpathViewController.h" #import "CGPathContainsPointViewController.h" #import "CGPathGetBoundingBoxViewController.h" +#import "CGPathAddArcViewController.h" +#import "CGPathAddArcToPointViewController.h" @interface CGContextNewTestsController () @@ -54,7 +56,7 @@ - (NSArray*)samples { if (!_samples) { _samples = @[ [CGContextSampleRow row:@"CGPathAddCurveToPoint" class:[CGPathAddCurveToPointViewController class]], - [CGContextSampleRow row:@"CGPathAddEllipse" class:[CGPathAddElipseViewController class]], + [CGContextSampleRow row:@"CGPathAddEllipseInRect" class:[CGPathAddElipseViewController class]], [CGContextSampleRow row:@"CGPathAddLineToPoint" class:[CGPathAddLineToPointViewController class]], [CGContextSampleRow row:@"CGPathAddPath" class:[CGPathAddPathViewController class]], [CGContextSampleRow row:@"CGPathAddQuadCurveToPoint" class:[CGPathAddQuadCurveToPointViewController class]], @@ -63,6 +65,8 @@ - (NSArray*)samples { [CGContextSampleRow row:@"CGPathCloseSubpath" class:[CGPathCloseSubpathViewController class]], [CGContextSampleRow row:@"CGPathContainsPoint" class:[CGPathContainsPointViewController class]], [CGContextSampleRow row:@"CGPathGetBoundingBox" class:[CGPathGetBoundingBoxViewController class]], + [CGContextSampleRow row:@"CGPathAddArc" class:[CGPathAddArcViewController class]], + [CGContextSampleRow row:@"CGPathAddArcToPoint" class:[CGPathAddArcToPointViewController class]], ]; } return _samples; @@ -184,19 +188,19 @@ - (void)loadView { self.redColor = [[UITextField alloc] initWithFrame:CGRectMake(200, 60, 50, 40)]; [self.redColor setBackgroundColor:[UIColor whiteColor]]; - [self.redColor setText:@"1.0"]; + [self.redColor setText:@"0"]; [self.redColor addTarget:self action:@selector(colorTextBoxCallBack:) forControlEvents:UIControlEventEditingChanged]; [self.view addSubview:self.redColor]; self.greenColor = [[UITextField alloc] initWithFrame:CGRectMake(230, 60, 50, 40)]; [self.greenColor setBackgroundColor:[UIColor whiteColor]]; - [self.greenColor setText:@"1.0"]; + [self.greenColor setText:@"0"]; [self.greenColor addTarget:self action:@selector(colorTextBoxCallBack:) forControlEvents:UIControlEventEditingChanged]; [self.view addSubview:self.greenColor]; self.blueColor = [[UITextField alloc] initWithFrame:CGRectMake(260, 60, 50, 40)]; [self.blueColor setBackgroundColor:[UIColor whiteColor]]; - [self.blueColor setText:@"1.0"]; + [self.blueColor setText:@"0"]; [self.blueColor addTarget:self action:@selector(colorTextBoxCallBack:) forControlEvents:UIControlEventEditingChanged]; [self.view addSubview:self.blueColor]; diff --git a/tests/unittests/CoreGraphics/CGPathTests.mm b/tests/unittests/CoreGraphics/CGPathTests.mm index d3ef0c5fee..58c0d6edb6 100644 --- a/tests/unittests/CoreGraphics/CGPathTests.mm +++ b/tests/unittests/CoreGraphics/CGPathTests.mm @@ -219,7 +219,7 @@ void cgPathCompare(NSArray* expected, NSArray* result) { CGPathRelease(path); } -DISABLED_TEST(CGPath, CGPathCreateMutableCopy) { +TEST(CGPath, CGPathCreateMutableCopy) { CGMutablePathRef path1 = CGPathCreateMutable(); CGRect rect = CGRectMake(2, 4, 8, 16); @@ -412,7 +412,7 @@ CGPathRef newPathForRoundRect(CGRect rect, CGFloat radius) { return path; } -DISABLED_TEST(CGPath, CGPathContainsPointOutsideRect) { +TEST(CGPath, CGPathContainsPointOutsideRect) { CGFloat originX = 10.0f; CGFloat originY = 20.0f; CGFloat pathWidth = 100.0f; @@ -438,7 +438,7 @@ CGPathRef newPathForRoundRect(CGRect rect, CGFloat radius) { EXPECT_FALSE(test); } -DISABLED_TEST(CGPath, CGPathContainsPointInsideRectOutsidePath) { +TEST(CGPath, CGPathContainsPointInsideRectOutsidePath) { CGFloat originX = 10.0f; CGFloat originY = 20.0f; CGFloat pathWidth = 100.0f; @@ -464,7 +464,7 @@ CGPathRef newPathForRoundRect(CGRect rect, CGFloat radius) { EXPECT_FALSE(test); } -DISABLED_TEST(CGPath, CGPathContainsPointShoulders) { +TEST(CGPath, CGPathContainsPointShoulders) { CGFloat originX = 10.0f; CGFloat originY = 20.0f; CGFloat pathWidth = 100.0f; @@ -501,7 +501,7 @@ CGPathRef newPathForRoundRect(CGRect rect, CGFloat radius) { EXPECT_TRUE(test); } -DISABLED_TEST(CGPath, CGPathContainsPointWithTransform) { +TEST(CGPath, CGPathContainsPointWithTransform) { CGFloat originX = 10.0f; CGFloat originY = 20.0f; CGFloat pathWidth = 100.0f; @@ -919,4 +919,47 @@ static bool testSymmetricEquivalence(CGPathRef path1, CGPathRef path2) { CGPathRelease(path1); CGPathRelease(path2); CGPathRelease(path3); +} + +TEST(CGPath, AddArcTest) { + CGMutablePathRef path = CGPathCreateMutable(); + + CGPathMoveToPoint(path, nullptr, 50, 50); + CGPathAddArc(path, nullptr, 100, 100, 75, 0, (-1 * M_PI / 2.0), true); + CGPathCloseSubpath(path); + + CGRect boundingBox = CGPathGetBoundingBox(path); + EXPECT_POINTEQ(boundingBox.origin, 50, 25); + EXPECT_SIZEEQ(boundingBox.size, 125, 75); + CGPathRelease(path); +} + +TEST(CGPath, PathEllipseInRect) { + CGMutablePathRef path = CGPathCreateMutable(); + + CGRect rectangle = CGRectMake(50, 50, 100, 100); + + CGPathMoveToPoint(path, nullptr, 50, 50); + CGPathAddEllipseInRect(path, nullptr, rectangle); + CGPathCloseSubpath(path); + + CGRect boundingBox = CGPathGetBoundingBox(path); + EXPECT_POINTEQ(boundingBox.origin, 50, 50); + EXPECT_SIZEEQ(boundingBox.size, 100, 100); + CGPathRelease(path); +} + +TEST(CGPath, CGPathAddArcToPoint) { + CGMutablePathRef thepath = CGPathCreateMutable(); + CGPathMoveToPoint(thepath, NULL, 50, 50); + CGPathAddArcToPoint(thepath, NULL, 50, 100, 100, 100, 10); + EXPECT_POINTEQ(CGPathGetCurrentPoint(thepath), 60, 100); + CGPathAddArcToPoint(thepath, NULL, 100, 100, 100, 50, 10); + EXPECT_POINTEQ(CGPathGetCurrentPoint(thepath), 100, 90); + CGPathCloseSubpath(thepath); + + CGRect boundingBox = CGPathGetBoundingBox(thepath); + EXPECT_POINTEQ(boundingBox.origin, 50, 50); + EXPECT_SIZEEQ(boundingBox.size, 50, 50); + CGPathRelease(thepath); } \ No newline at end of file From d4a3b0827878214039bcc6eb47ea9de0a0bbd593 Mon Sep 17 00:00:00 2001 From: Hank Fox Date: Thu, 17 Nov 2016 13:24:25 -0800 Subject: [PATCH 2/8] Implement transformations in terms of D2D simplify. --- Frameworks/CoreGraphics/CGContext.mm | 10 - Frameworks/CoreGraphics/CGPath.mm | 273 ++++++++++-------- Frameworks/include/CoreGraphics/D2DWrapper.h | 11 + .../CGCatalog-Headers.vcxitems | 1 + .../CGCatalog-Headers.vcxitems.filters | 3 + .../CGCatalog-WinStore10/CGCatalog.vcxproj | 1 + .../CGCatalog.vcxproj.filters | 5 + .../CGCatalog.xcodeproj/project.pbxproj | 6 + .../CGPathAddArcToPointViewController.m | 14 +- .../CGCatalog/CGPathAddArcViewController.m | 41 ++- .../CGPathAddCurveToPointViewController.m | 12 +- .../CGCatalog/CGPathAddElipseViewController.m | 5 +- .../CGPathAddLineToPointViewController.m | 24 +- .../CGCatalog/CGPathAddPathViewController.m | 26 +- .../CGPathAddQuadCurveToPointViewController.m | 18 +- .../CGCatalog/CGPathAddRectViewController.m | 8 +- .../CGPathAddRoundedRectViewController.h | 24 ++ .../CGPathAddRoundedRectViewController.m | 62 ++++ .../CGPathCloseSubpathViewController.m | 20 +- .../CGPathContainsPointViewController.m | 22 +- .../CGPathGetBoundingBoxViewController.m | 24 +- .../Samples/CGContextNewTestsController.m | 2 + .../unittests/CoreGraphics/CGContextTests.mm | 8 +- tests/unittests/CoreGraphics/CGPathTests.mm | 93 +++--- 24 files changed, 435 insertions(+), 278 deletions(-) create mode 100644 tests/testapps/CGCatalog/CGCatalog/CGPathAddRoundedRectViewController.h create mode 100644 tests/testapps/CGCatalog/CGCatalog/CGPathAddRoundedRectViewController.m diff --git a/Frameworks/CoreGraphics/CGContext.mm b/Frameworks/CoreGraphics/CGContext.mm index 7717a03f7d..e6d89e17e7 100644 --- a/Frameworks/CoreGraphics/CGContext.mm +++ b/Frameworks/CoreGraphics/CGContext.mm @@ -46,16 +46,6 @@ using namespace Microsoft::WRL; -static inline D2D_RECT_F __CGRectToD2D_F(CGRect rect) { - return { - rect.origin.x, rect.origin.y, rect.origin.x + rect.size.width, rect.origin.y + rect.size.height, - }; -} - -static inline D2D1_MATRIX_3X2_F __CGAffineTransformToD2D_F(CGAffineTransform transform) { - return { transform.a, transform.b, transform.c, transform.d, transform.tx, transform.ty }; -} - enum _CGCoordinateMode : unsigned int { _kCGCoordinateModeDeviceSpace = 0, _kCGCoordinateModeUserSpace }; struct __CGContextDrawingState { diff --git a/Frameworks/CoreGraphics/CGPath.mm b/Frameworks/CoreGraphics/CGPath.mm index d6e429368e..d58383a3af 100644 --- a/Frameworks/CoreGraphics/CGPath.mm +++ b/Frameworks/CoreGraphics/CGPath.mm @@ -34,7 +34,7 @@ static const wchar_t* TAG = L"CGPath"; -inline CGPoint __CreateCGPointWithTransform(CGFloat x, CGFloat y, const CGAffineTransform* transform) { +static inline CGPoint __CreateCGPointWithTransform(CGFloat x, CGFloat y, const CGAffineTransform* transform) { CGPoint pt{ x, y }; if (transform) { pt = CGPointApplyAffineTransform(pt, *transform); @@ -53,8 +53,9 @@ inline CGPoint __CreateCGPointWithTransform(CGFloat x, CGFloat y, const CGAffine bool figureClosed; CGPoint currentPoint{ 0, 0 }; CGPoint startingPoint{ 0, 0 }; + const CGAffineTransform* lastTransform; - __CGPath() : figureClosed(true) { + __CGPath() : figureClosed(true), lastTransform(&CGAffineTransformIdentity) { } ComPtr GetPathGeometry() { @@ -65,14 +66,6 @@ inline CGPoint __CreateCGPointWithTransform(CGFloat x, CGFloat y, const CGAffine return geometrySink; } - void SetPathGeometry(ComPtr path) { - pathGeometry = path; - } - - void SetGeometrySink(ComPtr sink) { - geometrySink = sink; - } - CGPoint GetCurrentPoint() { return currentPoint; } @@ -89,6 +82,18 @@ void SetStartingPoint(CGPoint newPoint) { startingPoint = newPoint; } + void SetLastTransform(const CGAffineTransform* transform) { + if (transform) { + lastTransform = transform; + } else { + lastTransform = &CGAffineTransformIdentity; + } + } + + const CGAffineTransform* GetLastTransform() { + return lastTransform; + } + // A private helper function for re-opening a path geometry. CGPath does not // have a concept of an open and a closed path but D2D relies on it. A // path/sink cannot be read from while the path is open thus it must be @@ -153,6 +158,19 @@ HRESULT InitializeGeometries() { return S_OK; } + + HRESULT SimplifyGeometryToPathWithTransformation(ComPtr geometry, const CGAffineTransform* transform) { + RETURN_IF_FAILED(ClosePath()); + RETURN_IF_FAILED(PreparePathForEditing()); + + D2D1_MATRIX_3X2_F transformation = D2D1::IdentityMatrix(); + if (transform) { + transformation = __CGAffineTransformToD2D_F(*transform); + } + RETURN_IF_FAILED( + geometry->Simplify(D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES, &transformation, GetGeometrySink().Get())); + return S_OK; + } }; HRESULT _CGPathGetGeometry(CGPathRef path, ID2D1Geometry** pGeometry) { @@ -236,6 +254,7 @@ CGMutablePathRef CGPathCreateMutableCopy(CGPathRef path) { mutableRet->SetCurrentPoint(path->GetCurrentPoint()); mutableRet->SetStartingPoint(path->GetStartingPoint()); + mutableRet->SetLastTransform(path->GetLastTransform()); return mutableRet; } @@ -252,10 +271,43 @@ void CGPathAddLineToPoint(CGMutablePathRef path, const CGAffineTransform* transf path->BeginFigure(); path->GetGeometrySink()->AddLine(_CGPointToD2D_F(pt)); + path->SetLastTransform(transform); path->SetCurrentPoint(pt); } +static inline bool _affineTransformEquals(const CGAffineTransform original, const CGAffineTransform compare) { + return (original.a != compare.a) && (original.b == compare.b) && (original.c == compare.c) && (original.d == compare.d) && + (original.tx == compare.tx) && (original.ty == compare.ty); +} + +static inline CGPoint _getInvertedCurrentPointOfPath(CGPathRef path) { + CGPoint point = path->GetCurrentPoint(); + if (!_affineTransformEquals(*path->GetLastTransform(), CGAffineTransformIdentity)) { + point = CGPointApplyAffineTransform(point, CGAffineTransformInvert(*path->GetLastTransform())); + } + return point; +} + +static HRESULT _createPathReadyForFigure(CGPathRef previousPath, + ID2D1PathGeometry** pathGeometry, + ID2D1GeometrySink** geometrySink, + CGPoint startPoint) { + ComPtr factory; + RETURN_IF_FAILED(_CGGetD2DFactory(&factory)); + RETURN_IF_FAILED(factory->CreatePathGeometry(pathGeometry)); + RETURN_IF_FAILED((*pathGeometry)->Open(geometrySink)); + + CGPoint invertedPoint = _getInvertedCurrentPointOfPath(previousPath); + if (!CGPointEqualToPoint(invertedPoint, startPoint)) { + (*geometrySink)->BeginFigure(_CGPointToD2D_F(invertedPoint), D2D1_FIGURE_BEGIN_FILLED); + (*geometrySink)->AddLine(_CGPointToD2D_F(startPoint)); + } else { + (*geometrySink)->BeginFigure(_CGPointToD2D_F(startPoint), D2D1_FIGURE_BEGIN_FILLED); + } + return S_OK; +} + /** @Status Interoperable */ @@ -263,19 +315,10 @@ void CGPathAddArcToPoint( CGMutablePathRef path, const CGAffineTransform* transform, CGFloat x1, CGFloat y1, CGFloat x2, CGFloat y2, CGFloat radius) { RETURN_IF(!path); - CGPoint curPathPosition = path->GetCurrentPoint(); - - CGPoint tangentPoint1 = __CreateCGPointWithTransform(x1, y1, transform); - CGPoint tangentPoint2 = __CreateCGPointWithTransform(x2, y2, transform); - - x1 = tangentPoint1.x; - y1 = tangentPoint1.y; + CGPoint invertedPoint = _getInvertedCurrentPointOfPath(path); - x2 = tangentPoint2.x; - y2 = tangentPoint2.y; - - CGFloat dx1 = x1 - curPathPosition.x; - CGFloat dy1 = y1 - curPathPosition.y; + CGFloat dx1 = x1 - invertedPoint.x; + CGFloat dy1 = y1 - invertedPoint.y; CGFloat dx2 = x1 - x2; CGFloat dy2 = y1 - y2; @@ -301,21 +344,33 @@ void CGPathAddArcToPoint( CGFloat tanPointBy = y1 - (tanLength * sin(endAngle)); CGPoint endPoint = CGPointMake(tanPointBx, tanPointBy); - const D2D1_POINT_2F endPointD2D = _CGPointToD2D_F(CGPointMake(tanPointBx, tanPointBy)); + const D2D1_POINT_2F endPointD2D = _CGPointToD2D_F(endPoint); + + int sweepSign = 1; + if (startAngle > endAngle) { + sweepSign = -1; + } + D2D1_SWEEP_DIRECTION sweepDirection = { startAngle + (M_PI * sweepSign) < endAngle ? D2D1_SWEEP_DIRECTION_CLOCKWISE : + D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE }; - D2D1_SWEEP_DIRECTION sweepDirection = { startAngle + M_PI < endAngle ? D2D1_SWEEP_DIRECTION_CLOCKWISE : - D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE }; const D2D1_SIZE_F radiusD2D = { radius, radius }; FLOAT rotationAngle = bisector * 2; D2D1_ARC_SIZE arcSize = D2D1_ARC_SIZE_SMALL; D2D1_ARC_SEGMENT arcSegment = D2D1::ArcSegment(endPointD2D, radiusD2D, rotationAngle, sweepDirection, arcSize); - // Append a line to the point we need to begin drawing the arc from. - FAIL_FAST_IF_FAILED(path->PreparePathForEditing()); - path->BeginFigure(); - CGPathAddLineToPoint(path, transform, tanPointAx, tanPointAy); + ComPtr newPath; + ComPtr newSink; + FAIL_FAST_IF_FAILED(_createPathReadyForFigure(path, &newPath, &newSink, CGPointMake(tanPointAx, tanPointAy))); + newSink->AddArc(arcSegment); + newSink->EndFigure(D2D1_FIGURE_END_OPEN); + FAIL_FAST_IF_FAILED(newSink->Close()); + + FAIL_FAST_IF_FAILED(path->SimplifyGeometryToPathWithTransformation(newPath, transform)); - path->GetGeometrySink()->AddArc(arcSegment); + if (transform) { + endPoint = CGPointApplyAffineTransform(endPoint, *transform); + } + path->SetLastTransform(transform); path->SetCurrentPoint(endPoint); } @@ -332,12 +387,8 @@ void CGPathAddArc(CGMutablePathRef path, bool clockwise) { RETURN_IF(!path); - CGPoint startPoint = __CreateCGPointWithTransform(x + radius * cos(startAngle), y + radius * sin(startAngle), transform); - CGPoint endPoint = __CreateCGPointWithTransform(x + radius * cos(endAngle), y + radius * sin(endAngle), transform); - - if (!CGPointEqualToPoint(path->GetCurrentPoint(), startPoint)) { - CGPathAddLineToPoint(path, nullptr, startPoint.x, startPoint.y); - } + CGPoint startPoint = CGPointMake(x + radius * cos(startAngle), y + radius * sin(startAngle)); + CGPoint endPoint = CGPointMake(x + radius * cos(endAngle), y + radius * sin(endAngle)); // Create the parameters for the AddArc method. const D2D1_POINT_2F endPointD2D = _CGPointToD2D_F(endPoint); @@ -357,10 +408,20 @@ void CGPathAddArc(CGMutablePathRef path, D2D1_SWEEP_DIRECTION sweepDirection = { clockwise ? D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE : D2D1_SWEEP_DIRECTION_CLOCKWISE }; D2D1_ARC_SEGMENT arcSegment = D2D1::ArcSegment(endPointD2D, radiusD2D, rotationAngle, sweepDirection, arcSize); - FAIL_FAST_IF_FAILED(path->PreparePathForEditing()); - path->BeginFigure(); - path->GetGeometrySink()->AddArc(arcSegment); + ComPtr newPath; + ComPtr newSink; + FAIL_FAST_IF_FAILED(_createPathReadyForFigure(path, &newPath, &newSink, startPoint)); + + newSink->AddArc(arcSegment); + newSink->EndFigure(D2D1_FIGURE_END_OPEN); + FAIL_FAST_IF_FAILED(newSink->Close()); + FAIL_FAST_IF_FAILED(path->SimplifyGeometryToPathWithTransformation(newPath, transform)); + + if (transform) { + endPoint = CGPointApplyAffineTransform(endPoint, *transform); + } + path->SetLastTransform(transform); path->SetCurrentPoint(endPoint); } @@ -377,6 +438,7 @@ void CGPathMoveToPoint(CGMutablePathRef path, const CGAffineTransform* transform CGPoint pt = __CreateCGPointWithTransform(x, y, transform); path->SetStartingPoint(pt); path->SetCurrentPoint(pt); + path->SetLastTransform(transform); } /** @@ -402,23 +464,28 @@ void CGPathAddRect(CGMutablePathRef path, const CGAffineTransform* transform, CG CGPathAddLineToPoint(path, transform, CGRectGetMaxX(rect), CGRectGetMaxY(rect)); CGPathAddLineToPoint(path, transform, CGRectGetMinX(rect), CGRectGetMaxY(rect)); CGPathCloseSubpath(path); + path->SetLastTransform(transform); } /** - @Status Caveat - @Notes Ignores Affine Transform + @Status Interoperable */ void CGPathAddPath(CGMutablePathRef path, const CGAffineTransform* transform, CGPathRef toAdd) { RETURN_IF(!path || !toAdd); - // Close the path we're adding and open the path we need to add to. + // Close the path being added. FAIL_FAST_IF_FAILED(toAdd->ClosePath()); + FAIL_FAST_IF_FAILED(path->SimplifyGeometryToPathWithTransformation(toAdd->GetPathGeometry(), transform)); - FAIL_FAST_IF_FAILED(path->PreparePathForEditing()); - path->EndFigure(D2D1_FIGURE_END_OPEN); - FAIL_FAST_IF_FAILED(toAdd->GetPathGeometry()->Stream(path->GetGeometrySink().Get())); - path->SetCurrentPoint(toAdd->GetCurrentPoint()); - path->SetStartingPoint(toAdd->GetStartingPoint()); + CGPoint currentPoint = toAdd->GetCurrentPoint(); + CGPoint startingPoint = toAdd->GetStartingPoint(); + if (transform) { + currentPoint = CGPointApplyAffineTransform(currentPoint, *transform); + startingPoint = CGPointApplyAffineTransform(startingPoint, *transform); + } + path->SetStartingPoint(startingPoint); + path->SetCurrentPoint(currentPoint); + path->SetLastTransform(transform); } /** @@ -426,40 +493,20 @@ void CGPathAddPath(CGMutablePathRef path, const CGAffineTransform* transform, CG */ void CGPathAddEllipseInRect(CGMutablePathRef path, const CGAffineTransform* transform, CGRect rect) { RETURN_IF(!path); - CGRect containingRectangle = rect; - // First we must transform the coordinates of the rectangle if necessary. - if (transform) { - containingRectangle = CGRectApplyAffineTransform(rect, *transform); - } - CGFloat radiusX = containingRectangle.size.width / 2.0; - CGFloat radiusY = containingRectangle.size.height / 2.0; - CGPoint center = CGPointMake(containingRectangle.origin.x + radiusX, containingRectangle.origin.y + radiusY); + CGFloat radiusX = rect.size.width / 2.0; + CGFloat radiusY = rect.size.height / 2.0; + CGPoint center = CGPointMake(rect.origin.x + radiusX, rect.origin.y + radiusY); D2D1_ELLIPSE ellipse = D2D1::Ellipse(_CGPointToD2D_F(center), radiusX, radiusY); - ComPtr factory; FAIL_FAST_IF_FAILED(_CGGetD2DFactory(&factory)); ComPtr ellipseGeometry; FAIL_FAST_IF_FAILED(factory->CreateEllipseGeometry(&ellipse, &ellipseGeometry)); - path->ClosePath(); - - // Create temp vars for new path/sink - ComPtr newPath; - ComPtr newSink; - - // Open a new path that the contents of the old path will be streamed into. We cannot re-use the same path as it is now closed - // and cannot be opened again. We use the newPath variable because the factory was returning the same pointer for some strange - // reason so this will force it to do otherwise. - FAIL_FAST_IF_FAILED(factory->CreatePathGeometry(&newPath)); - FAIL_FAST_IF_FAILED(newPath->Open(&newSink)); - - FAIL_FAST_IF_FAILED(ellipseGeometry->CombineWithGeometry(path->GetPathGeometry().Get(), D2D1_COMBINE_MODE_XOR, NULL, newSink.Get())); - - path->SetPathGeometry(newPath); - path->SetGeometrySink(newSink); + FAIL_FAST_IF_FAILED(path->SimplifyGeometryToPathWithTransformation(ellipseGeometry, transform)); + path->SetLastTransform(transform); } /** @@ -469,11 +516,13 @@ void CGPathCloseSubpath(CGMutablePathRef path) { RETURN_IF(!path); // Move the current point to the starting point since the line is closed. - // path->SetCurrentPoint(path->GetStartingPoint()); if (!CGPointEqualToPoint(path->GetStartingPoint(), path->GetCurrentPoint())) { CGPathAddLineToPoint(path, nullptr, path->GetStartingPoint().x, path->GetStartingPoint().y); } - path->EndFigure(D2D1_FIGURE_END_OPEN); // CLOSED); + + // Due to issues with streaming one geometry into another, the starting point of the D2D figure gets lost. + // Thus we draw our own closing line and declare the figure has ended. + path->EndFigure(D2D1_FIGURE_END_OPEN); } /** @@ -539,14 +588,24 @@ CGPathRef CGPathRetain(CGPathRef path) { void CGPathAddQuadCurveToPoint(CGMutablePathRef path, const CGAffineTransform* transform, CGFloat cpx, CGFloat cpy, CGFloat x, CGFloat y) { RETURN_IF(!path); - CGPoint endPoint = __CreateCGPointWithTransform(x, y, transform); - CGPoint controlPoint = __CreateCGPointWithTransform(cpx, cpy, transform); + CGPoint endPoint = CGPointMake(x, y); + CGPoint controlPoint = CGPointMake(cpx, cpy); - FAIL_FAST_IF_FAILED(path->PreparePathForEditing()); - path->BeginFigure(); - path->GetGeometrySink()->AddQuadraticBezier(D2D1::QuadraticBezierSegment(_CGPointToD2D_F(controlPoint), _CGPointToD2D_F(endPoint))); + ComPtr newPath; + ComPtr newSink; + + FAIL_FAST_IF_FAILED(_createPathReadyForFigure(path, &newPath, &newSink, _getInvertedCurrentPointOfPath(path))); + newSink->AddQuadraticBezier(D2D1::QuadraticBezierSegment(_CGPointToD2D_F(controlPoint), _CGPointToD2D_F(endPoint))); + newSink->EndFigure(D2D1_FIGURE_END_OPEN); + FAIL_FAST_IF_FAILED(newSink->Close()); + FAIL_FAST_IF_FAILED(path->SimplifyGeometryToPathWithTransformation(newPath, transform)); + + if (transform) { + endPoint = CGPointApplyAffineTransform(endPoint, *transform); + } path->SetCurrentPoint(endPoint); + path->SetLastTransform(transform); } /** @@ -562,24 +621,33 @@ void CGPathAddCurveToPoint(CGMutablePathRef path, CGFloat y) { RETURN_IF(!path); - CGPoint endPoint = __CreateCGPointWithTransform(x, y, transform); - CGPoint controlPoint1 = __CreateCGPointWithTransform(cp1x, cp1y, transform); - CGPoint controlPoint2 = __CreateCGPointWithTransform(cp2x, cp2y, transform); + CGPoint endPoint = CGPointMake(x, y); + CGPoint controlPoint1 = CGPointMake(cp1x, cp1y); + CGPoint controlPoint2 = CGPointMake(cp2x, cp2y); - FAIL_FAST_IF_FAILED(path->PreparePathForEditing()); - path->BeginFigure(); - path->GetGeometrySink()->AddBezier( - D2D1::BezierSegment(_CGPointToD2D_F(controlPoint1), _CGPointToD2D_F(controlPoint2), _CGPointToD2D_F(endPoint))); + ComPtr newPath; + ComPtr newSink; + + FAIL_FAST_IF_FAILED(_createPathReadyForFigure(path, &newPath, &newSink, _getInvertedCurrentPointOfPath(path))); + newSink->AddBezier(D2D1::BezierSegment(_CGPointToD2D_F(controlPoint1), _CGPointToD2D_F(controlPoint2), _CGPointToD2D_F(endPoint))); + newSink->EndFigure(D2D1_FIGURE_END_OPEN); + FAIL_FAST_IF_FAILED(newSink->Close()); + + FAIL_FAST_IF_FAILED(path->SimplifyGeometryToPathWithTransformation(newPath, transform)); + if (transform) { + endPoint = CGPointApplyAffineTransform(endPoint, *transform); + } path->SetCurrentPoint(endPoint); + path->SetLastTransform(transform); } /** @Status Interoperable */ -CGPathRef CGPathCreateWithRect(CGRect rect, const CGAffineTransform* trans) { +CGPathRef CGPathCreateWithRect(CGRect rect, const CGAffineTransform* transform) { CGMutablePathRef ret = CGPathCreateMutable(); - CGPathAddRect(ret, trans, rect); + CGPathAddRect(ret, transform, rect); return (CGPathRef)ret; } @@ -619,12 +687,6 @@ void CGPathAddRelativeArc( UNIMPLEMENTED(); } -static inline D2D_RECT_F __CGRectToD2D_F(CGRect rect) { - return { - rect.origin.x, rect.origin.y, rect.origin.x + rect.size.width, rect.origin.y + rect.size.height, - }; -} - /** @Status Interoperable @Notes @@ -633,11 +695,6 @@ void CGPathAddRoundedRect( CGMutablePathRef path, const CGAffineTransform* transform, CGRect rect, CGFloat cornerWidth, CGFloat cornerHeight) { RETURN_IF(!path); - // First we must transform the coordinates of the rectangle if necessary. - if (transform) { - rect = CGRectApplyAffineTransform(rect, *transform); - } - D2D1_RECT_F rectangle = __CGRectToD2D_F(rect); D2D1_ROUNDED_RECT roundedRectangle = { rectangle, cornerWidth, cornerHeight }; @@ -647,21 +704,8 @@ void CGPathAddRoundedRect( FAIL_FAST_IF_FAILED(factory->CreateRoundedRectangleGeometry(&roundedRectangle, &rectangleGeometry)); - path->ClosePath(); - - // Create temp vars for new path/sink - ComPtr newPath; - ComPtr newSink; - - // Open a new path that the contents of the old path will be streamed into. We cannot re-use the same path as it is now closed - // and cannot be opened again. - FAIL_FAST_IF_FAILED(factory->CreatePathGeometry(&newPath)); - FAIL_FAST_IF_FAILED(newPath->Open(&newSink)); - - FAIL_FAST_IF_FAILED(rectangleGeometry->CombineWithGeometry(path->GetPathGeometry().Get(), D2D1_COMBINE_MODE_XOR, NULL, newSink.Get())); - - path->SetPathGeometry(newPath); - path->SetGeometrySink(newSink); + FAIL_FAST_IF_FAILED(path->SimplifyGeometryToPathWithTransformation(rectangleGeometry, transform)); + path->SetLastTransform(transform); } int _CGPathPointCountForElementType(CGPathElementType type) { @@ -756,7 +800,6 @@ CGMutablePathRef CGPathCreateMutableCopyByTransformingPath(CGPathRef path, const CGPathRef CGPathCreateWithRoundedRect(CGRect rect, CGFloat cornerWidth, CGFloat cornerHeight, const CGAffineTransform* transform) { CGMutablePathRef ret = CGPathCreateMutable(); CGPathAddRoundedRect(ret, transform, rect, cornerWidth, cornerHeight); - return (CGPathRef)ret; } diff --git a/Frameworks/include/CoreGraphics/D2DWrapper.h b/Frameworks/include/CoreGraphics/D2DWrapper.h index 0ec8ed9441..64c1281870 100644 --- a/Frameworks/include/CoreGraphics/D2DWrapper.h +++ b/Frameworks/include/CoreGraphics/D2DWrapper.h @@ -22,6 +22,7 @@ #import "Wincodec.h" #include +#import #import #import @@ -42,4 +43,14 @@ inline CGRect _D2DRectToCGRect(D2D1_RECT_F rect) { CGFloat height = rect.bottom - y; return CGRectMake(x, y, width, height); +} + +inline D2D1_MATRIX_3X2_F __CGAffineTransformToD2D_F(CGAffineTransform transform) { + return { transform.a, transform.b, transform.c, transform.d, transform.tx, transform.ty }; +} + +inline D2D_RECT_F __CGRectToD2D_F(CGRect rect) { + return { + rect.origin.x, rect.origin.y, rect.origin.x + rect.size.width, rect.origin.y + rect.size.height, + }; } \ No newline at end of file diff --git a/tests/testapps/CGCatalog/CGCatalog.vsimporter/CGCatalog-Headers-WinStore10/CGCatalog-Headers.vcxitems b/tests/testapps/CGCatalog/CGCatalog.vsimporter/CGCatalog-Headers-WinStore10/CGCatalog-Headers.vcxitems index aeb452f183..dddd5017b1 100644 --- a/tests/testapps/CGCatalog/CGCatalog.vsimporter/CGCatalog-Headers-WinStore10/CGCatalog-Headers.vcxitems +++ b/tests/testapps/CGCatalog/CGCatalog.vsimporter/CGCatalog-Headers-WinStore10/CGCatalog-Headers.vcxitems @@ -17,6 +17,7 @@ + diff --git a/tests/testapps/CGCatalog/CGCatalog.vsimporter/CGCatalog-Headers-WinStore10/CGCatalog-Headers.vcxitems.filters b/tests/testapps/CGCatalog/CGCatalog.vsimporter/CGCatalog-Headers-WinStore10/CGCatalog-Headers.vcxitems.filters index eae9baf05e..e55af5e378 100644 --- a/tests/testapps/CGCatalog/CGCatalog.vsimporter/CGCatalog-Headers-WinStore10/CGCatalog-Headers.vcxitems.filters +++ b/tests/testapps/CGCatalog/CGCatalog.vsimporter/CGCatalog-Headers-WinStore10/CGCatalog-Headers.vcxitems.filters @@ -99,5 +99,8 @@ CGCatalog\NewSamples + + CGCatalog\NewSamples + \ No newline at end of file diff --git a/tests/testapps/CGCatalog/CGCatalog.vsimporter/CGCatalog-WinStore10/CGCatalog.vcxproj b/tests/testapps/CGCatalog/CGCatalog.vsimporter/CGCatalog-WinStore10/CGCatalog.vcxproj index 2f64bbe473..370dabbc11 100644 --- a/tests/testapps/CGCatalog/CGCatalog.vsimporter/CGCatalog-WinStore10/CGCatalog.vcxproj +++ b/tests/testapps/CGCatalog/CGCatalog.vsimporter/CGCatalog-WinStore10/CGCatalog.vcxproj @@ -192,6 +192,7 @@ + diff --git a/tests/testapps/CGCatalog/CGCatalog.vsimporter/CGCatalog-WinStore10/CGCatalog.vcxproj.filters b/tests/testapps/CGCatalog/CGCatalog.vsimporter/CGCatalog-WinStore10/CGCatalog.vcxproj.filters index b851c38d90..a3e24f5f7b 100644 --- a/tests/testapps/CGCatalog/CGCatalog.vsimporter/CGCatalog-WinStore10/CGCatalog.vcxproj.filters +++ b/tests/testapps/CGCatalog/CGCatalog.vsimporter/CGCatalog-WinStore10/CGCatalog.vcxproj.filters @@ -200,6 +200,8 @@ + + @@ -211,6 +213,9 @@ CGCatalog\NewSamples + + CGCatalog\NewSamples + diff --git a/tests/testapps/CGCatalog/CGCatalog.xcodeproj/project.pbxproj b/tests/testapps/CGCatalog/CGCatalog.xcodeproj/project.pbxproj index 610d857d6d..c0616b419c 100644 --- a/tests/testapps/CGCatalog/CGCatalog.xcodeproj/project.pbxproj +++ b/tests/testapps/CGCatalog/CGCatalog.xcodeproj/project.pbxproj @@ -15,6 +15,7 @@ 8B2360561DD690CC008F4EBF /* CGPathAddArcToPointViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B2360551DD690CC008F4EBF /* CGPathAddArcToPointViewController.m */; }; 8B2360591DDAACAE008F4EBF /* AddArc.png in Resources */ = {isa = PBXBuildFile; fileRef = 8B2360571DDAACAE008F4EBF /* AddArc.png */; }; 8B23605A1DDAACAE008F4EBF /* AddArcToPoint.png in Resources */ = {isa = PBXBuildFile; fileRef = 8B2360581DDAACAE008F4EBF /* AddArcToPoint.png */; }; + 8B23605D1DDBAC23008F4EBF /* CGPathAddRoundedRectViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B23605C1DDBAC23008F4EBF /* CGPathAddRoundedRectViewController.m */; }; 8B2D2E821D9DA57700B8E557 /* AddCurveToPoint.png in Resources */ = {isa = PBXBuildFile; fileRef = 8B2D2E7D1D9DA57700B8E557 /* AddCurveToPoint.png */; }; 8B2D2E831D9DA57700B8E557 /* AddElipseToRect.png in Resources */ = {isa = PBXBuildFile; fileRef = 8B2D2E7E1D9DA57700B8E557 /* AddElipseToRect.png */; }; 8B2D2E841D9DA57700B8E557 /* AddLineToPoint.png in Resources */ = {isa = PBXBuildFile; fileRef = 8B2D2E7F1D9DA57700B8E557 /* AddLineToPoint.png */; }; @@ -69,6 +70,8 @@ 8B2360551DD690CC008F4EBF /* CGPathAddArcToPointViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CGPathAddArcToPointViewController.m; sourceTree = ""; }; 8B2360571DDAACAE008F4EBF /* AddArc.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AddArc.png; sourceTree = ""; }; 8B2360581DDAACAE008F4EBF /* AddArcToPoint.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AddArcToPoint.png; sourceTree = ""; }; + 8B23605B1DDBAC23008F4EBF /* CGPathAddRoundedRectViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CGPathAddRoundedRectViewController.h; sourceTree = ""; }; + 8B23605C1DDBAC23008F4EBF /* CGPathAddRoundedRectViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CGPathAddRoundedRectViewController.m; sourceTree = ""; }; 8B2D2E7D1D9DA57700B8E557 /* AddCurveToPoint.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AddCurveToPoint.png; sourceTree = ""; }; 8B2D2E7E1D9DA57700B8E557 /* AddElipseToRect.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AddElipseToRect.png; sourceTree = ""; }; 8B2D2E7F1D9DA57700B8E557 /* AddLineToPoint.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AddLineToPoint.png; sourceTree = ""; }; @@ -150,6 +153,8 @@ 8BC8830E1D90A33F009115D0 /* NewSamples */ = { isa = PBXGroup; children = ( + 8B23605B1DDBAC23008F4EBF /* CGPathAddRoundedRectViewController.h */, + 8B23605C1DDBAC23008F4EBF /* CGPathAddRoundedRectViewController.m */, 8B2360541DD690CC008F4EBF /* CGPathAddArcToPointViewController.h */, 8B2360551DD690CC008F4EBF /* CGPathAddArcToPointViewController.m */, 8B2360511DC92A90008F4EBF /* CGPathAddArcViewController.h */, @@ -384,6 +389,7 @@ 5579D6771D1B73EC00B33059 /* CGCCGPathContainsPointViewController.m in Sources */, 8B2360561DD690CC008F4EBF /* CGPathAddArcToPointViewController.m in Sources */, F0D21C861D05FEF9002C32EE /* AppDelegate.m in Sources */, + 8B23605D1DDBAC23008F4EBF /* CGPathAddRoundedRectViewController.m in Sources */, 8B9D65131D89C5EB00153CCF /* CGContextSampleRow.m in Sources */, F0D21CBF1D06078D002C32EE /* CGCBaseViewController.m in Sources */, FB18A4BA1D1AD10A00A9555A /* CGCCGContextBeginTransparencyLayerWithRect.m in Sources */, diff --git a/tests/testapps/CGCatalog/CGCatalog/CGPathAddArcToPointViewController.m b/tests/testapps/CGCatalog/CGCatalog/CGPathAddArcToPointViewController.m index 30672b47bf..51b23fab0f 100644 --- a/tests/testapps/CGCatalog/CGCatalog/CGPathAddArcToPointViewController.m +++ b/tests/testapps/CGCatalog/CGCatalog/CGPathAddArcToPointViewController.m @@ -36,13 +36,15 @@ - (void)loadView { CGContextSetStrokeColorWithColor(currentContext, self.options.lineColor); CGContextSetLineDash(currentContext, self.options.linePhase, self.options.lineDashPattern, self.options.lineDashCount); + CGAffineTransform transformation = CGAffineTransformIdentity; + CGMutablePathRef thepath = CGPathCreateMutable(); - CGPathMoveToPoint(thepath, NULL, 75, 100); - CGPathAddArcToPoint(thepath, NULL, 50, 150, 100, 250, 15); - CGPathAddArcToPoint(thepath, NULL, 100, 250, 150, 150, 15); - CGPathAddArcToPoint(thepath, NULL, 150, 150, 100, 50, 15); - CGPathAddArcToPoint(thepath, NULL, 100, 50, 50, 150, 15); - CGPathAddLineToPoint(thepath, NULL, 75, 100); + CGPathMoveToPoint(thepath, &transformation, 75, 100); + CGPathAddArcToPoint(thepath, &transformation, 50, 150, 100, 250, 15); + CGPathAddArcToPoint(thepath, &transformation, 100, 250, 150, 150, 15); + CGPathAddArcToPoint(thepath, &transformation, 150, 150, 100, 50, 15); + CGPathAddArcToPoint(thepath, &transformation, 100, 50, 50, 150, 15); + CGPathAddLineToPoint(thepath, &transformation, 75, 100); CGContextAddPath(currentContext, thepath); diff --git a/tests/testapps/CGCatalog/CGCatalog/CGPathAddArcViewController.m b/tests/testapps/CGCatalog/CGCatalog/CGPathAddArcViewController.m index 8e09e0c04d..a4d6754b56 100644 --- a/tests/testapps/CGCatalog/CGCatalog/CGPathAddArcViewController.m +++ b/tests/testapps/CGCatalog/CGCatalog/CGPathAddArcViewController.m @@ -19,11 +19,6 @@ @implementation CGPathAddArcViewController -- (id)initWithDrawingOptions:(CGDrawOptions*)options { - self = [super initWithDrawingOptions:options]; - return self; -} - - (void)loadView { [super loadView]; [self.view setBackgroundColor:[UIColor clearColor]]; @@ -36,28 +31,30 @@ - (void)loadView { CGContextSetStrokeColorWithColor(currentContext, self.options.lineColor); CGContextSetLineDash(currentContext, self.options.linePhase, self.options.lineDashPattern, self.options.lineDashCount); + CGAffineTransform transformation = CGAffineTransformIdentity; + CGMutablePathRef thepath = CGPathCreateMutable(); - CGPathMoveToPoint(thepath, NULL, 100, 100); - CGPathAddArc(thepath, NULL, 100, 100, 75, 0, M_PI / 2, true); + CGPathMoveToPoint(thepath, &transformation, 100, 100); + CGPathAddArc(thepath, &transformation, 100, 100, 75, 0, M_PI / 2, true); CGPathCloseSubpath(thepath); - CGPathMoveToPoint(thepath, NULL, 110, 90); - CGPathAddArc(thepath, NULL, 110, 90, 75, M_PI / 2, 0, true); + CGPathMoveToPoint(thepath, &transformation, 110, 90); + CGPathAddArc(thepath, &transformation, 110, 90, 75, M_PI / 2, 0, true); CGPathCloseSubpath(thepath); - CGPathMoveToPoint(thepath, NULL, 400, 150); - CGPathAddArc(thepath, NULL, 300, 150, 100, 0, M_PI / 2, true); - CGPathAddArc(thepath, NULL, 300, 150, 100, M_PI / 2, 0, true); - CGPathMoveToPoint(thepath, NULL, 200, 150); - CGPathAddArc(thepath, NULL, 250, 150, 50, M_PI, 0, false); - CGPathMoveToPoint(thepath, NULL, 300, 150); - CGPathAddArc(thepath, NULL, 350, 150, 50, M_PI, 0, true); - CGPathMoveToPoint(thepath, NULL, 275, 150); - CGPathAddArc(thepath, NULL, 250, 150, 25, 0, M_PI / 2, true); - CGPathAddArc(thepath, NULL, 250, 150, 25, M_PI / 2, 0, true); - CGPathMoveToPoint(thepath, NULL, 375, 150); - CGPathAddArc(thepath, NULL, 350, 150, 25, 0, M_PI / 2, true); - CGPathAddArc(thepath, NULL, 350, 150, 25, M_PI / 2, 0, true); + CGPathMoveToPoint(thepath, &transformation, 400, 150); + CGPathAddArc(thepath, &transformation, 300, 150, 100, 0, M_PI / 2, true); + CGPathAddArc(thepath, &transformation, 300, 150, 100, M_PI / 2, 0, true); + CGPathMoveToPoint(thepath, &transformation, 200, 150); + CGPathAddArc(thepath, &transformation, 250, 150, 50, M_PI, 0, false); + CGPathMoveToPoint(thepath, &transformation, 300, 150); + CGPathAddArc(thepath, &transformation, 350, 150, 50, M_PI, 0, true); + CGPathMoveToPoint(thepath, &transformation, 275, 150); + CGPathAddArc(thepath, &transformation, 250, 150, 25, 0, M_PI / 2, true); + CGPathAddArc(thepath, &transformation, 250, 150, 25, M_PI / 2, 0, true); + CGPathMoveToPoint(thepath, &transformation, 375, 150); + CGPathAddArc(thepath, &transformation, 350, 150, 25, 0, M_PI / 2, true); + CGPathAddArc(thepath, &transformation, 350, 150, 25, M_PI / 2, 0, true); CGContextAddPath(currentContext, thepath); diff --git a/tests/testapps/CGCatalog/CGCatalog/CGPathAddCurveToPointViewController.m b/tests/testapps/CGCatalog/CGCatalog/CGPathAddCurveToPointViewController.m index 1cd3f22743..5e6138ccd9 100644 --- a/tests/testapps/CGCatalog/CGCatalog/CGPathAddCurveToPointViewController.m +++ b/tests/testapps/CGCatalog/CGCatalog/CGPathAddCurveToPointViewController.m @@ -36,13 +36,15 @@ - (void)loadView { CGContextSetStrokeColorWithColor(currentContext, self.options.lineColor); CGContextSetLineDash(currentContext, self.options.linePhase, self.options.lineDashPattern, self.options.lineDashCount); + CGAffineTransform transformation = CGAffineTransformIdentity; + CGMutablePathRef thepath = CGPathCreateMutable(); - CGPathMoveToPoint(thepath, NULL, 30, 100); - CGPathAddCurveToPoint(thepath, NULL, 47.0f, 67.0f, 50.0f, 55.0f, 45.0f, 50.0f); - CGPathAddCurveToPoint(thepath, NULL, 42.0f, 47.0f, 37.0f, 46.0f, 30.0f, 55.0f); + CGPathMoveToPoint(thepath, &transformation, 30, 100); + CGPathAddCurveToPoint(thepath, &transformation, 47.0f, 67.0f, 50.0f, 55.0f, 45.0f, 50.0f); + CGPathAddCurveToPoint(thepath, &transformation, 42.0f, 47.0f, 37.0f, 46.0f, 30.0f, 55.0f); - CGPathAddCurveToPoint(thepath, NULL, 23.0f, 46.0f, 18.0f, 47.0f, 15.0f, 50.0f); - CGPathAddCurveToPoint(thepath, NULL, 10.0f, 55.0f, 13.0f, 67.0f, 30.0f, 100.0f); + CGPathAddCurveToPoint(thepath, &transformation, 23.0f, 46.0f, 18.0f, 47.0f, 15.0f, 50.0f); + CGPathAddCurveToPoint(thepath, &transformation, 10.0f, 55.0f, 13.0f, 67.0f, 30.0f, 100.0f); CGPathCloseSubpath(thepath); CGContextAddPath(currentContext, thepath); diff --git a/tests/testapps/CGCatalog/CGCatalog/CGPathAddElipseViewController.m b/tests/testapps/CGCatalog/CGCatalog/CGPathAddElipseViewController.m index 1172ece4c4..6394c04ada 100644 --- a/tests/testapps/CGCatalog/CGCatalog/CGPathAddElipseViewController.m +++ b/tests/testapps/CGCatalog/CGCatalog/CGPathAddElipseViewController.m @@ -39,7 +39,10 @@ - (void)loadView { CGMutablePathRef thepath = CGPathCreateMutable(); - CGPathAddEllipseInRect(thepath, NULL, theRectangle); + CGAffineTransform transformation = CGAffineTransformIdentity; + transformation = CGAffineTransformRotate(transformation, 0.1); + + CGPathAddEllipseInRect(thepath, &transformation, theRectangle); CGPathCloseSubpath(thepath); CGContextAddPath(currentContext, thepath); CGContextStrokePath(currentContext); diff --git a/tests/testapps/CGCatalog/CGCatalog/CGPathAddLineToPointViewController.m b/tests/testapps/CGCatalog/CGCatalog/CGPathAddLineToPointViewController.m index aa633f2504..56f7e8866a 100644 --- a/tests/testapps/CGCatalog/CGCatalog/CGPathAddLineToPointViewController.m +++ b/tests/testapps/CGCatalog/CGCatalog/CGPathAddLineToPointViewController.m @@ -35,20 +35,22 @@ - (void)loadView { CGContextSetStrokeColorWithColor(currentContext, self.options.lineColor); CGContextSetLineDash(currentContext, self.options.linePhase, self.options.lineDashPattern, self.options.lineDashCount); + CGAffineTransform transformation = CGAffineTransformIdentity; + CGMutablePathRef thepath = CGPathCreateMutable(); - CGPathMoveToPoint(thepath, NULL, 200, 35); - CGPathAddLineToPoint(thepath, NULL, 165, 100); - CGPathAddLineToPoint(thepath, NULL, 100, 100); - CGPathAddLineToPoint(thepath, NULL, 150, 150); - CGPathAddLineToPoint(thepath, NULL, 135, 225); - CGPathAddLineToPoint(thepath, NULL, 200, 170); - CGPathAddLineToPoint(thepath, NULL, 265, 225); - CGPathAddLineToPoint(thepath, NULL, 250, 150); - CGPathAddLineToPoint(thepath, NULL, 300, 100); - CGPathAddLineToPoint(thepath, NULL, 235, 100); + CGPathMoveToPoint(thepath, &transformation, 200, 35); + CGPathAddLineToPoint(thepath, &transformation, 165, 100); + CGPathAddLineToPoint(thepath, &transformation, 100, 100); + CGPathAddLineToPoint(thepath, &transformation, 150, 150); + CGPathAddLineToPoint(thepath, &transformation, 135, 225); + CGPathAddLineToPoint(thepath, &transformation, 200, 170); + CGPathAddLineToPoint(thepath, &transformation, 265, 225); + CGPathAddLineToPoint(thepath, &transformation, 250, 150); + CGPathAddLineToPoint(thepath, &transformation, 300, 100); + CGPathAddLineToPoint(thepath, &transformation, 235, 100); // Unnecessary as close subpath will finish this line off but for the sake of consistency, have this here. - CGPathAddLineToPoint(thepath, NULL, 200, 35); + CGPathAddLineToPoint(thepath, &transformation, 200, 35); CGPathCloseSubpath(thepath); CGContextAddPath(currentContext, thepath); diff --git a/tests/testapps/CGCatalog/CGCatalog/CGPathAddPathViewController.m b/tests/testapps/CGCatalog/CGCatalog/CGPathAddPathViewController.m index fbf36bfafb..d7b542e7ef 100644 --- a/tests/testapps/CGCatalog/CGCatalog/CGPathAddPathViewController.m +++ b/tests/testapps/CGCatalog/CGCatalog/CGPathAddPathViewController.m @@ -38,21 +38,23 @@ - (void)loadView { CGMutablePathRef theFirstPath = CGPathCreateMutable(); CGMutablePathRef theSecondPath = CGPathCreateMutable(); - CGPathMoveToPoint(theFirstPath, NULL, 200, 35); - CGPathAddLineToPoint(theFirstPath, NULL, 165, 100); - CGPathAddLineToPoint(theFirstPath, NULL, 100, 100); - CGPathAddLineToPoint(theFirstPath, NULL, 150, 150); - CGPathAddLineToPoint(theFirstPath, NULL, 135, 225); - CGPathAddLineToPoint(theFirstPath, NULL, 200, 170); - CGPathAddLineToPoint(theFirstPath, NULL, 265, 225); + CGAffineTransform transformation = CGAffineTransformIdentity; - CGPathMoveToPoint(theSecondPath, NULL, 265, 225); + CGPathMoveToPoint(theFirstPath, &transformation, 200, 35); + CGPathAddLineToPoint(theFirstPath, &transformation, 165, 100); + CGPathAddLineToPoint(theFirstPath, &transformation, 100, 100); + CGPathAddLineToPoint(theFirstPath, &transformation, 150, 150); + CGPathAddLineToPoint(theFirstPath, &transformation, 135, 225); + CGPathAddLineToPoint(theFirstPath, &transformation, 200, 170); + CGPathAddLineToPoint(theFirstPath, &transformation, 265, 225); - CGPathAddLineToPoint(theSecondPath, NULL, 350, 225); - CGPathAddLineToPoint(theSecondPath, NULL, 350, 35); - CGPathAddLineToPoint(theSecondPath, NULL, 200, 35); + CGPathMoveToPoint(theSecondPath, &transformation, 265, 225); - CGPathAddPath(theFirstPath, NULL, theSecondPath); + CGPathAddLineToPoint(theSecondPath, &transformation, 350, 225); + CGPathAddLineToPoint(theSecondPath, &transformation, 350, 35); + CGPathAddLineToPoint(theSecondPath, &transformation, 200, 35); + + CGPathAddPath(theFirstPath, &transformation, theSecondPath); CGContextAddPath(currentContext, theFirstPath); // Closing the path will close the subpath created from adding the second path to the first. diff --git a/tests/testapps/CGCatalog/CGCatalog/CGPathAddQuadCurveToPointViewController.m b/tests/testapps/CGCatalog/CGCatalog/CGPathAddQuadCurveToPointViewController.m index ad8ddaff28..0bba1d829c 100644 --- a/tests/testapps/CGCatalog/CGCatalog/CGPathAddQuadCurveToPointViewController.m +++ b/tests/testapps/CGCatalog/CGCatalog/CGPathAddQuadCurveToPointViewController.m @@ -35,19 +35,21 @@ - (void)loadView { CGContextSetStrokeColorWithColor(currentContext, self.options.lineColor); CGContextSetLineDash(currentContext, self.options.linePhase, self.options.lineDashPattern, self.options.lineDashCount); + CGAffineTransform transformation = CGAffineTransformIdentity; + CGMutablePathRef thePath = CGPathCreateMutable(); - CGPathMoveToPoint(thePath, NULL, 100, 50); - CGPathAddQuadCurveToPoint(thePath, NULL, 125, 25, 150, 50); + CGPathMoveToPoint(thePath, &transformation, 100, 50); + CGPathAddQuadCurveToPoint(thePath, &transformation, 125, 25, 150, 50); - CGPathMoveToPoint(thePath, NULL, 200, 50); - CGPathAddQuadCurveToPoint(thePath, NULL, 225, 25, 250, 50); + CGPathMoveToPoint(thePath, &transformation, 200, 50); + CGPathAddQuadCurveToPoint(thePath, &transformation, 225, 25, 250, 50); - CGPathMoveToPoint(thePath, NULL, 100, 150); - CGPathAddQuadCurveToPoint(thePath, NULL, 200, 200, 300, 100); + CGPathMoveToPoint(thePath, &transformation, 100, 150); + CGPathAddQuadCurveToPoint(thePath, &transformation, 200, 200, 300, 100); - CGPathMoveToPoint(thePath, NULL, 285, 105); - CGPathAddQuadCurveToPoint(thePath, NULL, 300, 90, 310, 110); + CGPathMoveToPoint(thePath, &transformation, 285, 105); + CGPathAddQuadCurveToPoint(thePath, &transformation, 300, 90, 310, 110); CGContextAddPath(currentContext, thePath); diff --git a/tests/testapps/CGCatalog/CGCatalog/CGPathAddRectViewController.m b/tests/testapps/CGCatalog/CGCatalog/CGPathAddRectViewController.m index 40615334db..b8813c98cc 100644 --- a/tests/testapps/CGCatalog/CGCatalog/CGPathAddRectViewController.m +++ b/tests/testapps/CGCatalog/CGCatalog/CGPathAddRectViewController.m @@ -37,10 +37,12 @@ - (void)loadView { CGMutablePathRef thePath = CGPathCreateMutable(); - CGPathMoveToPoint(thePath, NULL, 50, 50); - CGPathAddLineToPoint(thePath, NULL, 100, 100); + CGAffineTransform transformation = CGAffineTransformIdentity; - CGPathAddRect(thePath, NULL, CGRectMake(100, 100, 200, 100)); + CGPathMoveToPoint(thePath, &transformation, 50, 50); + CGPathAddLineToPoint(thePath, &transformation, 100, 100); + + CGPathAddRect(thePath, &transformation, CGRectMake(100, 100, 200, 100)); CGContextAddPath(currentContext, thePath); diff --git a/tests/testapps/CGCatalog/CGCatalog/CGPathAddRoundedRectViewController.h b/tests/testapps/CGCatalog/CGCatalog/CGPathAddRoundedRectViewController.h new file mode 100644 index 0000000000..a352970eea --- /dev/null +++ b/tests/testapps/CGCatalog/CGCatalog/CGPathAddRoundedRectViewController.h @@ -0,0 +1,24 @@ +//****************************************************************************** +// +// Copyright (c) Microsoft. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +//****************************************************************************** + +#pragma once + +#import "CGCBaseViewController.h" +#import +#import "CGSamplePage.h" + +@interface CGPathAddRoundedRectViewController : CGCBaseViewController +@end diff --git a/tests/testapps/CGCatalog/CGCatalog/CGPathAddRoundedRectViewController.m b/tests/testapps/CGCatalog/CGCatalog/CGPathAddRoundedRectViewController.m new file mode 100644 index 0000000000..b1fcbe40a9 --- /dev/null +++ b/tests/testapps/CGCatalog/CGCatalog/CGPathAddRoundedRectViewController.m @@ -0,0 +1,62 @@ +//****************************************************************************** +// +// Copyright (c) Microsoft. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +//****************************************************************************** + +#import "CGPathAddRoundedRectViewController.h" +#import "CGDrawView.h" + +@implementation CGPathAddRoundedRectViewController + +- (id)initWithDrawingOptions:(CGDrawOptions*)options { + self = [super initWithDrawingOptions:options]; + return self; +} + +- (void)loadView { + [super loadView]; + [self.view setBackgroundColor:[UIColor clearColor]]; + + CGDrawView* drawView = [[CGDrawView alloc] initWithFrame:self.view.bounds drawOptions:self.options]; + [drawView setDrawBlock:^(void) { + CGContextRef currentContext = UIGraphicsGetCurrentContext(); + + CGContextSetLineWidth(currentContext, self.options.lineWidth); + CGContextSetStrokeColorWithColor(currentContext, self.options.lineColor); + CGContextSetLineDash(currentContext, self.options.linePhase, self.options.lineDashPattern, self.options.lineDashCount); + + CGAffineTransform transformation = CGAffineTransformIdentity; + + CGMutablePathRef thepath = CGPathCreateMutable(); + CGPathMoveToPoint(thepath, &transformation, 75, 100); + CGRect rect = CGRectMake(75, 100, 100, 100); + CGPathAddRoundedRect(thepath, &transformation, rect, 25, 25); + rect = CGRectMake(200, 100, 100, 100); + CGPathAddRoundedRect(thepath, &transformation, rect, 50, 50); + + CGContextAddPath(currentContext, thepath); + + CGContextStrokePath(currentContext); + + CGPathRelease(thepath); + + [super drawComparisonCGImageFromImageName:@"AddArcToPoint" intoContext:currentContext]; + }]; + + [self.view addSubview:drawView]; + + [super addComparisonLabel]; +} + +@end diff --git a/tests/testapps/CGCatalog/CGCatalog/CGPathCloseSubpathViewController.m b/tests/testapps/CGCatalog/CGCatalog/CGPathCloseSubpathViewController.m index ab766c5d21..5f77084e4c 100644 --- a/tests/testapps/CGCatalog/CGCatalog/CGPathCloseSubpathViewController.m +++ b/tests/testapps/CGCatalog/CGCatalog/CGPathCloseSubpathViewController.m @@ -35,20 +35,22 @@ - (void)loadView { CGContextSetStrokeColorWithColor(currentContext, self.options.lineColor); CGContextSetLineDash(currentContext, self.options.linePhase, self.options.lineDashPattern, self.options.lineDashCount); + CGAffineTransform transformation = CGAffineTransformIdentity; + CGMutablePathRef thePath = CGPathCreateMutable(); - CGPathMoveToPoint(thePath, NULL, 50, 50); - CGPathAddLineToPoint(thePath, NULL, 50, 100); - CGPathAddLineToPoint(thePath, NULL, 100, 100); + CGPathMoveToPoint(thePath, &transformation, 50, 50); + CGPathAddLineToPoint(thePath, &transformation, 50, 100); + CGPathAddLineToPoint(thePath, &transformation, 100, 100); CGPathCloseSubpath(thePath); - CGPathMoveToPoint(thePath, NULL, 200, 50); - CGPathAddLineToPoint(thePath, NULL, 200, 100); - CGPathAddLineToPoint(thePath, NULL, 150, 100); + CGPathMoveToPoint(thePath, &transformation, 200, 50); + CGPathAddLineToPoint(thePath, &transformation, 200, 100); + CGPathAddLineToPoint(thePath, &transformation, 150, 100); CGPathCloseSubpath(thePath); - CGPathMoveToPoint(thePath, NULL, 100, 200); - CGPathAddLineToPoint(thePath, NULL, 125, 150); - CGPathAddLineToPoint(thePath, NULL, 150, 200); + CGPathMoveToPoint(thePath, &transformation, 100, 200); + CGPathAddLineToPoint(thePath, &transformation, 125, 150); + CGPathAddLineToPoint(thePath, &transformation, 150, 200); CGPathCloseSubpath(thePath); CGPathCloseSubpath(thePath); diff --git a/tests/testapps/CGCatalog/CGCatalog/CGPathContainsPointViewController.m b/tests/testapps/CGCatalog/CGCatalog/CGPathContainsPointViewController.m index 2089354aa2..6dd04e177f 100644 --- a/tests/testapps/CGCatalog/CGCatalog/CGPathContainsPointViewController.m +++ b/tests/testapps/CGCatalog/CGCatalog/CGPathContainsPointViewController.m @@ -51,17 +51,19 @@ - (void)loadView { CGContextSetStrokeColorWithColor(currentContext, weakSelf.options.lineColor); CGContextSetLineDash(currentContext, weakSelf.options.linePhase, weakSelf.options.lineDashPattern, weakSelf.options.lineDashCount); + CGAffineTransform transformation = CGAffineTransformIdentity; + weakSelf.containingPath = CGPathCreateMutable(); - CGPathMoveToPoint(weakSelf.containingPath, NULL, 200, 35); - CGPathAddLineToPoint(weakSelf.containingPath, NULL, 165, 100); - CGPathAddLineToPoint(weakSelf.containingPath, NULL, 100, 100); - CGPathAddLineToPoint(weakSelf.containingPath, NULL, 150, 150); - CGPathAddLineToPoint(weakSelf.containingPath, NULL, 135, 225); - CGPathAddLineToPoint(weakSelf.containingPath, NULL, 200, 170); - CGPathAddLineToPoint(weakSelf.containingPath, NULL, 265, 225); - CGPathAddLineToPoint(weakSelf.containingPath, NULL, 250, 150); - CGPathAddLineToPoint(weakSelf.containingPath, NULL, 300, 100); - CGPathAddLineToPoint(weakSelf.containingPath, NULL, 235, 100); + CGPathMoveToPoint(weakSelf.containingPath, &transformation, 200, 35); + CGPathAddLineToPoint(weakSelf.containingPath, &transformation, 165, 100); + CGPathAddLineToPoint(weakSelf.containingPath, &transformation, 100, 100); + CGPathAddLineToPoint(weakSelf.containingPath, &transformation, 150, 150); + CGPathAddLineToPoint(weakSelf.containingPath, &transformation, 135, 225); + CGPathAddLineToPoint(weakSelf.containingPath, &transformation, 200, 170); + CGPathAddLineToPoint(weakSelf.containingPath, &transformation, 265, 225); + CGPathAddLineToPoint(weakSelf.containingPath, &transformation, 250, 150); + CGPathAddLineToPoint(weakSelf.containingPath, &transformation, 300, 100); + CGPathAddLineToPoint(weakSelf.containingPath, &transformation, 235, 100); // Unnecessary as close subpath will finish this line off but for the sake of consistency, have this here. CGPathAddLineToPoint(weakSelf.containingPath, NULL, 200, 35); diff --git a/tests/testapps/CGCatalog/CGCatalog/CGPathGetBoundingBoxViewController.m b/tests/testapps/CGCatalog/CGCatalog/CGPathGetBoundingBoxViewController.m index 958b496607..241c72baca 100644 --- a/tests/testapps/CGCatalog/CGCatalog/CGPathGetBoundingBoxViewController.m +++ b/tests/testapps/CGCatalog/CGCatalog/CGPathGetBoundingBoxViewController.m @@ -35,18 +35,20 @@ - (void)loadView { CGContextSetStrokeColorWithColor(currentContext, self.options.lineColor); CGContextSetLineDash(currentContext, self.options.linePhase, self.options.lineDashPattern, self.options.lineDashCount); + CGAffineTransform transformation = CGAffineTransformIdentity; + CGMutablePathRef thepath = CGPathCreateMutable(); - CGPathMoveToPoint(thepath, NULL, 200, 35); - CGPathAddLineToPoint(thepath, NULL, 165, 100); - CGPathAddLineToPoint(thepath, NULL, 100, 100); - CGPathAddLineToPoint(thepath, NULL, 150, 150); - CGPathAddLineToPoint(thepath, NULL, 135, 225); - CGPathAddLineToPoint(thepath, NULL, 200, 170); - CGPathAddLineToPoint(thepath, NULL, 265, 225); - CGPathAddLineToPoint(thepath, NULL, 250, 150); - CGPathAddLineToPoint(thepath, NULL, 300, 100); - CGPathAddLineToPoint(thepath, NULL, 235, 100); - CGPathAddLineToPoint(thepath, NULL, 200, 35); + CGPathMoveToPoint(thepath, &transformation, 200, 35); + CGPathAddLineToPoint(thepath, &transformation, 165, 100); + CGPathAddLineToPoint(thepath, &transformation, 100, 100); + CGPathAddLineToPoint(thepath, &transformation, 150, 150); + CGPathAddLineToPoint(thepath, &transformation, 135, 225); + CGPathAddLineToPoint(thepath, &transformation, 200, 170); + CGPathAddLineToPoint(thepath, &transformation, 265, 225); + CGPathAddLineToPoint(thepath, &transformation, 250, 150); + CGPathAddLineToPoint(thepath, &transformation, 300, 100); + CGPathAddLineToPoint(thepath, &transformation, 235, 100); + CGPathAddLineToPoint(thepath, &transformation, 200, 35); CGPathCloseSubpath(thepath); CGContextAddPath(currentContext, thepath); diff --git a/tests/testapps/CGCatalog/CGCatalog/Samples/CGContextNewTestsController.m b/tests/testapps/CGCatalog/CGCatalog/Samples/CGContextNewTestsController.m index 114d219d5d..778ffc3f5e 100644 --- a/tests/testapps/CGCatalog/CGCatalog/Samples/CGContextNewTestsController.m +++ b/tests/testapps/CGCatalog/CGCatalog/Samples/CGContextNewTestsController.m @@ -31,6 +31,7 @@ #import "CGPathGetBoundingBoxViewController.h" #import "CGPathAddArcViewController.h" #import "CGPathAddArcToPointViewController.h" +#import "CGPathAddRoundedRectViewController.h" @interface CGContextNewTestsController () @@ -67,6 +68,7 @@ - (NSArray*)samples { [CGContextSampleRow row:@"CGPathGetBoundingBox" class:[CGPathGetBoundingBoxViewController class]], [CGContextSampleRow row:@"CGPathAddArc" class:[CGPathAddArcViewController class]], [CGContextSampleRow row:@"CGPathAddArcToPoint" class:[CGPathAddArcToPointViewController class]], + [CGContextSampleRow row:@"CGPathAddRoundedRect" class:[CGPathAddRoundedRectViewController class]], ]; } return _samples; diff --git a/tests/unittests/CoreGraphics/CGContextTests.mm b/tests/unittests/CoreGraphics/CGContextTests.mm index db3c20b9a4..30db606df1 100644 --- a/tests/unittests/CoreGraphics/CGContextTests.mm +++ b/tests/unittests/CoreGraphics/CGContextTests.mm @@ -78,6 +78,10 @@ void cgContextPathApplierFunction(void* info, const CGPathElement* element) { [result addObject:@{ kTypeKey : @(element->type), kPointsKey : points }]; } +inline bool operator==(const CGPoint& lhs, const CGPoint& rhs) { + return ((std::abs(lhs.x - rhs.x) < 0.00001) && (std::abs(lhs.y - rhs.y) < 0.00001)); +} + // Helper function that compares results from cgPathApplierFunction to expected results void cgContextPathCompare(NSArray* expected, NSArray* result) { ASSERT_EQ(expected.count, result.count) << "Counts do not match for expected and result"; @@ -276,10 +280,6 @@ void cgContextPathCompare(NSArray* expected, NSArray* result) { CGColorSpaceRelease(rgbColorSpace); } -bool operator==(const CGPoint& lhs, const CGPoint& rhs) { - return ((std::abs(lhs.x - rhs.x) < 0.00001) && (std::abs(lhs.y - rhs.y) < 0.00001)); -} - template std::basic_ostream& operator<<(std::basic_ostream& os, const CGPoint& pt) { return os << "{" << pt.x << ", " << pt.y << "}"; diff --git a/tests/unittests/CoreGraphics/CGPathTests.mm b/tests/unittests/CoreGraphics/CGPathTests.mm index 58c0d6edb6..7d737b8d25 100644 --- a/tests/unittests/CoreGraphics/CGPathTests.mm +++ b/tests/unittests/CoreGraphics/CGPathTests.mm @@ -18,6 +18,7 @@ #import #import #import +#import #import #import @@ -583,16 +584,6 @@ CGPathRef newPathForRoundRect(CGRect rect, CGFloat radius) { EXPECT_TRUE(test); } -void EXPECT_POINTEQ(CGPoint pathPoint, CGFloat x, CGFloat y) { - EXPECT_EQ(x, pathPoint.x); - EXPECT_EQ(y, pathPoint.y); -} - -void EXPECT_SIZEEQ(CGSize pathSize, CGFloat width, CGFloat height) { - EXPECT_EQ(width, pathSize.width); - EXPECT_EQ(height, pathSize.height); -} - // Simple tests for the status of a CGPath during the CGPath rework into D2D. TEST(CGPath, CGPathSimpleCreation) { // Create a new path @@ -600,26 +591,26 @@ void EXPECT_SIZEEQ(CGSize pathSize, CGFloat width, CGFloat height) { EXPECT_TRUE(CGPathIsEmpty(path)); EXPECT_NE(nullptr, path); // Its starting point should be at 0,0 - EXPECT_POINTEQ(CGPathGetCurrentPoint(path), 0, 0); + EXPECT_EQ(CGPathGetCurrentPoint(path), CGPointMake(0, 0)); // Move to a new point CGPathMoveToPoint(path, nullptr, 50, 50); - EXPECT_POINTEQ(CGPathGetCurrentPoint(path), 50, 50); + EXPECT_EQ(CGPathGetCurrentPoint(path), CGPointMake(50, 50)); // Move to another new point CGPathMoveToPoint(path, nullptr, 100, 50); - EXPECT_POINTEQ(CGPathGetCurrentPoint(path), 100, 50); + EXPECT_EQ(CGPathGetCurrentPoint(path), CGPointMake(100, 50)); // Create a copy of this path which should be at the same point CGMutablePathRef pathCopy = CGPathCreateMutableCopy(path); - EXPECT_POINTEQ(CGPathGetCurrentPoint(pathCopy), 100, 50); + EXPECT_EQ(CGPathGetCurrentPoint(pathCopy), CGPointMake(100, 50)); // Move the new path to a new point CGPathMoveToPoint(pathCopy, nullptr, 200, 200); // The original should not have been changed but the new path should have moved - EXPECT_POINTEQ(CGPathGetCurrentPoint(path), 100, 50); - EXPECT_POINTEQ(CGPathGetCurrentPoint(pathCopy), 200, 200); + EXPECT_EQ(CGPathGetCurrentPoint(path), CGPointMake(100, 50)); + EXPECT_EQ(CGPathGetCurrentPoint(pathCopy), CGPointMake(200, 200)); CGPathRelease(path); CGPathRelease(pathCopy); @@ -630,12 +621,12 @@ void EXPECT_SIZEEQ(CGSize pathSize, CGFloat width, CGFloat height) { CGMutablePathRef path = CGPathCreateMutable(); CGPathMoveToPoint(path, nullptr, 50, 50); CGPathAddLineToPoint(path, nullptr, 25, 25); - EXPECT_POINTEQ(CGPathGetCurrentPoint(path), 25, 25); + EXPECT_EQ(CGPathGetCurrentPoint(path), CGPointMake(25, 25)); // Get the size of its bounding box CGRect boundingBox = CGPathGetBoundingBox(path); - EXPECT_POINTEQ(boundingBox.origin, 25, 25); - EXPECT_SIZEEQ(boundingBox.size, 25, 25); + EXPECT_EQ(boundingBox.origin, CGPointMake(25, 25)); + EXPECT_EQ(boundingBox.size, CGSizeMake(25, 25)); // Add a line further down to increase the bounding box's size CGPathAddLineToPoint(path, nullptr, 100, 200); @@ -643,8 +634,8 @@ void EXPECT_SIZEEQ(CGSize pathSize, CGFloat width, CGFloat height) { boundingBox = CGPathGetBoundingBox(path); // Verify that the size of this box has changed - EXPECT_POINTEQ(boundingBox.origin, 25, 25); - EXPECT_SIZEEQ(boundingBox.size, 75, 175); + EXPECT_EQ(boundingBox.origin, CGPointMake(25, 25)); + EXPECT_EQ(boundingBox.size, CGSizeMake(75, 175)); CGPathRelease(path); // Create a new path and move it to a new point @@ -654,8 +645,8 @@ void EXPECT_SIZEEQ(CGSize pathSize, CGFloat width, CGFloat height) { // Get the bounding box size of that path boundingBox = CGPathGetBoundingBox(path); - EXPECT_POINTEQ(boundingBox.origin, 50, 50); - EXPECT_SIZEEQ(boundingBox.size, 31, 57); + EXPECT_EQ(boundingBox.origin, CGPointMake(50, 50)); + EXPECT_EQ(boundingBox.size, CGSizeMake(31, 57)); // Create a copy of this path CGMutablePathRef pathCopy = CGPathCreateMutableCopy(path); @@ -663,17 +654,17 @@ void EXPECT_SIZEEQ(CGSize pathSize, CGFloat width, CGFloat height) { // Check that original bounding box has not changed. boundingBox = CGPathGetBoundingBox(path); - EXPECT_POINTEQ(boundingBox.origin, 50, 50); - EXPECT_SIZEEQ(boundingBox.size, 31, 57); + EXPECT_EQ(boundingBox.origin, CGPointMake(50, 50)); + EXPECT_EQ(boundingBox.size, CGSizeMake(31, 57)); boundingBox = CGPathGetBoundingBox(pathCopy); - EXPECT_POINTEQ(boundingBox.origin, 50, 50); - EXPECT_SIZEEQ(boundingBox.size, 150, 150); + EXPECT_EQ(boundingBox.origin, CGPointMake(50, 50)); + EXPECT_EQ(boundingBox.size, CGSizeMake(150, 150)); // Redundant check for confidence boundingBox = CGPathGetBoundingBox(path); - EXPECT_POINTEQ(boundingBox.origin, 50, 50); - EXPECT_SIZEEQ(boundingBox.size, 31, 57); + EXPECT_EQ(boundingBox.origin, CGPointMake(50, 50)); + EXPECT_EQ(boundingBox.size, CGSizeMake(31, 57)); CGPathRelease(path); CGPathRelease(pathCopy); @@ -689,17 +680,17 @@ void EXPECT_SIZEEQ(CGSize pathSize, CGFloat width, CGFloat height) { CGPathAddLineToPoint(secondPath, nullptr, 100, 100); CGRect boundingBox = CGPathGetBoundingBox(path); - EXPECT_POINTEQ(boundingBox.origin, 50, 50); - EXPECT_SIZEEQ(boundingBox.size, 25, 25); + EXPECT_EQ(boundingBox.origin, CGPointMake(50, 50)); + EXPECT_EQ(boundingBox.size, CGSizeMake(25, 25)); boundingBox = CGPathGetBoundingBox(secondPath); - EXPECT_POINTEQ(boundingBox.origin, 75, 75); - EXPECT_SIZEEQ(boundingBox.size, 25, 25); + EXPECT_EQ(boundingBox.origin, CGPointMake(75, 75)); + EXPECT_EQ(boundingBox.size, CGSizeMake(25, 25)); CGPathAddPath(path, nullptr, secondPath); boundingBox = CGPathGetBoundingBox(path); - EXPECT_POINTEQ(boundingBox.origin, 50, 50); - EXPECT_SIZEEQ(boundingBox.size, 50, 50); + EXPECT_EQ(boundingBox.origin, CGPointMake(50, 50)); + EXPECT_EQ(boundingBox.size, CGSizeMake(50, 50)); CGPathRelease(path); CGPathRelease(secondPath); @@ -710,8 +701,8 @@ void EXPECT_SIZEEQ(CGSize pathSize, CGFloat width, CGFloat height) { CGMutablePathRef path = CGPathCreateWithRect(theRectangle, nullptr); CGRect boundingBox = CGPathGetBoundingBox(path); - EXPECT_POINTEQ(boundingBox.origin, theRectangle.origin.x, theRectangle.origin.y); - EXPECT_SIZEEQ(boundingBox.size, theRectangle.size.height, theRectangle.size.width); + EXPECT_EQ(boundingBox.origin, theRectangle.origin); + EXPECT_EQ(boundingBox.size, theRectangle.size); CGPathRelease(path); path = CGPathCreateMutable(); @@ -722,8 +713,8 @@ void EXPECT_SIZEEQ(CGSize pathSize, CGFloat width, CGFloat height) { boundingBox = CGPathGetBoundingBox(path); - EXPECT_POINTEQ(boundingBox.origin, 50, 50); - EXPECT_SIZEEQ(boundingBox.size, 250, 150); + EXPECT_EQ(boundingBox.origin, CGPointMake(50, 50)); + EXPECT_EQ(boundingBox.size, CGSizeMake(250, 150)); CGPathRelease(path); } @@ -739,8 +730,8 @@ void EXPECT_SIZEEQ(CGSize pathSize, CGFloat width, CGFloat height) { CGRect boundingBox = CGPathGetBoundingBox(path); - EXPECT_POINTEQ(boundingBox.origin, 50, 50); - EXPECT_SIZEEQ(boundingBox.size, 50, 50); + EXPECT_EQ(boundingBox.origin, CGPointMake(50, 50)); + EXPECT_EQ(boundingBox.size, CGSizeMake(50, 50)); CGPoint newPoints[] = { { 100, 100 }, { 200, 25 }, { 100, 100 }, { 25, 200 } }; @@ -748,8 +739,8 @@ void EXPECT_SIZEEQ(CGSize pathSize, CGFloat width, CGFloat height) { boundingBox = CGPathGetBoundingBox(path); - EXPECT_POINTEQ(boundingBox.origin, 25, 25); - EXPECT_SIZEEQ(boundingBox.size, 175, 175); + EXPECT_EQ(boundingBox.origin, CGPointMake(25, 25)); + EXPECT_EQ(boundingBox.size, CGSizeMake(175, 175)); CGPathRelease(path); } @@ -929,8 +920,8 @@ static bool testSymmetricEquivalence(CGPathRef path1, CGPathRef path2) { CGPathCloseSubpath(path); CGRect boundingBox = CGPathGetBoundingBox(path); - EXPECT_POINTEQ(boundingBox.origin, 50, 25); - EXPECT_SIZEEQ(boundingBox.size, 125, 75); + EXPECT_EQ(boundingBox.origin, CGPointMake(50, 25)); + EXPECT_EQ(boundingBox.size, CGSizeMake(125, 75)); CGPathRelease(path); } @@ -944,8 +935,8 @@ static bool testSymmetricEquivalence(CGPathRef path1, CGPathRef path2) { CGPathCloseSubpath(path); CGRect boundingBox = CGPathGetBoundingBox(path); - EXPECT_POINTEQ(boundingBox.origin, 50, 50); - EXPECT_SIZEEQ(boundingBox.size, 100, 100); + EXPECT_EQ(boundingBox.origin, CGPointMake(50, 50)); + EXPECT_EQ(boundingBox.size, CGSizeMake(100, 100)); CGPathRelease(path); } @@ -953,13 +944,13 @@ static bool testSymmetricEquivalence(CGPathRef path1, CGPathRef path2) { CGMutablePathRef thepath = CGPathCreateMutable(); CGPathMoveToPoint(thepath, NULL, 50, 50); CGPathAddArcToPoint(thepath, NULL, 50, 100, 100, 100, 10); - EXPECT_POINTEQ(CGPathGetCurrentPoint(thepath), 60, 100); + EXPECT_EQ(CGPathGetCurrentPoint(thepath), CGPointMake(60, 100)); CGPathAddArcToPoint(thepath, NULL, 100, 100, 100, 50, 10); - EXPECT_POINTEQ(CGPathGetCurrentPoint(thepath), 100, 90); + EXPECT_EQ(CGPathGetCurrentPoint(thepath), CGPointMake(100, 90)); CGPathCloseSubpath(thepath); CGRect boundingBox = CGPathGetBoundingBox(thepath); - EXPECT_POINTEQ(boundingBox.origin, 50, 50); - EXPECT_SIZEEQ(boundingBox.size, 50, 50); + EXPECT_EQ(boundingBox.origin, CGPointMake(50, 50)); + EXPECT_EQ(boundingBox.size, CGSizeMake(50, 50)); CGPathRelease(thepath); } \ No newline at end of file From ae892532efd533e36dbc287083eb775868640291 Mon Sep 17 00:00:00 2001 From: Hank Fox Date: Mon, 21 Nov 2016 12:57:58 -0800 Subject: [PATCH 3/8] Update curves, test app with Transformation options. --- Frameworks/CoreGraphics/CGPath.mm | 12 +- .../CGCatalog/CGCatalog/CGDrawOptions.h | 4 +- .../CGCatalog/CGCatalog/CGDrawOptions.m | 4 +- .../CGPathAddArcToPointViewController.m | 2 +- .../CGCatalog/CGPathAddArcViewController.m | 2 +- .../CGPathAddCurveToPointViewController.m | 2 +- .../CGCatalog/CGPathAddElipseViewController.m | 3 +- .../CGPathAddLineToPointViewController.m | 2 +- .../CGCatalog/CGPathAddPathViewController.m | 2 +- .../CGPathAddQuadCurveToPointViewController.m | 2 +- .../CGCatalog/CGPathAddRectViewController.m | 2 +- .../CGPathAddRoundedRectViewController.m | 2 +- .../CGPathCloseSubpathViewController.m | 2 +- .../CGPathContainsPointViewController.m | 4 +- .../CGPathGetBoundingBoxViewController.m | 2 +- .../Samples/CGContextNewTestsController.m | 154 +++++++++++++++++- .../unittests/CoreGraphics/CGContextTests.mm | 2 +- tests/unittests/CoreGraphics/CGPathTests.mm | 4 +- 18 files changed, 180 insertions(+), 27 deletions(-) diff --git a/Frameworks/CoreGraphics/CGPath.mm b/Frameworks/CoreGraphics/CGPath.mm index d58383a3af..594ce7a23e 100644 --- a/Frameworks/CoreGraphics/CGPath.mm +++ b/Frameworks/CoreGraphics/CGPath.mm @@ -53,9 +53,9 @@ static inline CGPoint __CreateCGPointWithTransform(CGFloat x, CGFloat y, const C bool figureClosed; CGPoint currentPoint{ 0, 0 }; CGPoint startingPoint{ 0, 0 }; - const CGAffineTransform* lastTransform; + CGAffineTransform lastTransform; - __CGPath() : figureClosed(true), lastTransform(&CGAffineTransformIdentity) { + __CGPath() : figureClosed(true), lastTransform(CGAffineTransformIdentity) { } ComPtr GetPathGeometry() { @@ -82,16 +82,16 @@ void SetStartingPoint(CGPoint newPoint) { startingPoint = newPoint; } - void SetLastTransform(const CGAffineTransform* transform) { + const void SetLastTransform(const CGAffineTransform* transform) { if (transform) { - lastTransform = transform; + lastTransform = *transform; } else { - lastTransform = &CGAffineTransformIdentity; + lastTransform = CGAffineTransformIdentity; } } const CGAffineTransform* GetLastTransform() { - return lastTransform; + return &lastTransform; } // A private helper function for re-opening a path geometry. CGPath does not diff --git a/tests/testapps/CGCatalog/CGCatalog/CGDrawOptions.h b/tests/testapps/CGCatalog/CGCatalog/CGDrawOptions.h index d2c0ac3e8d..64a79969d9 100644 --- a/tests/testapps/CGCatalog/CGCatalog/CGDrawOptions.h +++ b/tests/testapps/CGCatalog/CGCatalog/CGDrawOptions.h @@ -22,7 +22,8 @@ fillColor:(CGColorRef)fillColor lineDashPattern:(CGFloat*)dashPattern linePhase:(CGFloat)linePhase - dashCount:(size_t)dashCount; + dashCount:(size_t)dashCount + transform:(CGAffineTransform)transform; @property (readonly) CGFloat lineWidth; @property (readonly) CGColorRef lineColor; @@ -30,4 +31,5 @@ @property (readonly) CGFloat* lineDashPattern; @property (readonly) CGFloat linePhase; @property (readonly) size_t lineDashCount; +@property (readonly) CGAffineTransform affineTransform; @end diff --git a/tests/testapps/CGCatalog/CGCatalog/CGDrawOptions.m b/tests/testapps/CGCatalog/CGCatalog/CGDrawOptions.m index e836a3eaaf..ba448b7baa 100644 --- a/tests/testapps/CGCatalog/CGCatalog/CGDrawOptions.m +++ b/tests/testapps/CGCatalog/CGCatalog/CGDrawOptions.m @@ -24,7 +24,8 @@ - (id)initWithLineWidth:(CGFloat)lineWidth fillColor:(CGColorRef)fillColor lineDashPattern:(CGFloat*)dashPattern linePhase:(CGFloat)linePhase - dashCount:(size_t)dashCount { + dashCount:(size_t)dashCount + transform:(CGAffineTransform)transform { if (self = [super init]) { _lineWidth = lineWidth; _lineColor = lineColor; @@ -34,6 +35,7 @@ - (id)initWithLineWidth:(CGFloat)lineWidth _lineDashPattern = dashPattern; _linePhase = linePhase; _lineDashCount = dashCount; + _affineTransform = transform; } return self; } diff --git a/tests/testapps/CGCatalog/CGCatalog/CGPathAddArcToPointViewController.m b/tests/testapps/CGCatalog/CGCatalog/CGPathAddArcToPointViewController.m index 51b23fab0f..7d80ffd9e5 100644 --- a/tests/testapps/CGCatalog/CGCatalog/CGPathAddArcToPointViewController.m +++ b/tests/testapps/CGCatalog/CGCatalog/CGPathAddArcToPointViewController.m @@ -36,7 +36,7 @@ - (void)loadView { CGContextSetStrokeColorWithColor(currentContext, self.options.lineColor); CGContextSetLineDash(currentContext, self.options.linePhase, self.options.lineDashPattern, self.options.lineDashCount); - CGAffineTransform transformation = CGAffineTransformIdentity; + CGAffineTransform transformation = self.options.affineTransform; CGMutablePathRef thepath = CGPathCreateMutable(); CGPathMoveToPoint(thepath, &transformation, 75, 100); diff --git a/tests/testapps/CGCatalog/CGCatalog/CGPathAddArcViewController.m b/tests/testapps/CGCatalog/CGCatalog/CGPathAddArcViewController.m index a4d6754b56..172c53ff23 100644 --- a/tests/testapps/CGCatalog/CGCatalog/CGPathAddArcViewController.m +++ b/tests/testapps/CGCatalog/CGCatalog/CGPathAddArcViewController.m @@ -31,7 +31,7 @@ - (void)loadView { CGContextSetStrokeColorWithColor(currentContext, self.options.lineColor); CGContextSetLineDash(currentContext, self.options.linePhase, self.options.lineDashPattern, self.options.lineDashCount); - CGAffineTransform transformation = CGAffineTransformIdentity; + CGAffineTransform transformation = self.options.affineTransform; CGMutablePathRef thepath = CGPathCreateMutable(); CGPathMoveToPoint(thepath, &transformation, 100, 100); diff --git a/tests/testapps/CGCatalog/CGCatalog/CGPathAddCurveToPointViewController.m b/tests/testapps/CGCatalog/CGCatalog/CGPathAddCurveToPointViewController.m index 5e6138ccd9..791c3f1b47 100644 --- a/tests/testapps/CGCatalog/CGCatalog/CGPathAddCurveToPointViewController.m +++ b/tests/testapps/CGCatalog/CGCatalog/CGPathAddCurveToPointViewController.m @@ -36,7 +36,7 @@ - (void)loadView { CGContextSetStrokeColorWithColor(currentContext, self.options.lineColor); CGContextSetLineDash(currentContext, self.options.linePhase, self.options.lineDashPattern, self.options.lineDashCount); - CGAffineTransform transformation = CGAffineTransformIdentity; + CGAffineTransform transformation = self.options.affineTransform; CGMutablePathRef thepath = CGPathCreateMutable(); CGPathMoveToPoint(thepath, &transformation, 30, 100); diff --git a/tests/testapps/CGCatalog/CGCatalog/CGPathAddElipseViewController.m b/tests/testapps/CGCatalog/CGCatalog/CGPathAddElipseViewController.m index 6394c04ada..d610b0aace 100644 --- a/tests/testapps/CGCatalog/CGCatalog/CGPathAddElipseViewController.m +++ b/tests/testapps/CGCatalog/CGCatalog/CGPathAddElipseViewController.m @@ -39,8 +39,7 @@ - (void)loadView { CGMutablePathRef thepath = CGPathCreateMutable(); - CGAffineTransform transformation = CGAffineTransformIdentity; - transformation = CGAffineTransformRotate(transformation, 0.1); + CGAffineTransform transformation = self.options.affineTransform; CGPathAddEllipseInRect(thepath, &transformation, theRectangle); CGPathCloseSubpath(thepath); diff --git a/tests/testapps/CGCatalog/CGCatalog/CGPathAddLineToPointViewController.m b/tests/testapps/CGCatalog/CGCatalog/CGPathAddLineToPointViewController.m index 56f7e8866a..878f1284c2 100644 --- a/tests/testapps/CGCatalog/CGCatalog/CGPathAddLineToPointViewController.m +++ b/tests/testapps/CGCatalog/CGCatalog/CGPathAddLineToPointViewController.m @@ -35,7 +35,7 @@ - (void)loadView { CGContextSetStrokeColorWithColor(currentContext, self.options.lineColor); CGContextSetLineDash(currentContext, self.options.linePhase, self.options.lineDashPattern, self.options.lineDashCount); - CGAffineTransform transformation = CGAffineTransformIdentity; + CGAffineTransform transformation = self.options.affineTransform; CGMutablePathRef thepath = CGPathCreateMutable(); CGPathMoveToPoint(thepath, &transformation, 200, 35); diff --git a/tests/testapps/CGCatalog/CGCatalog/CGPathAddPathViewController.m b/tests/testapps/CGCatalog/CGCatalog/CGPathAddPathViewController.m index d7b542e7ef..300b5ebb61 100644 --- a/tests/testapps/CGCatalog/CGCatalog/CGPathAddPathViewController.m +++ b/tests/testapps/CGCatalog/CGCatalog/CGPathAddPathViewController.m @@ -38,7 +38,7 @@ - (void)loadView { CGMutablePathRef theFirstPath = CGPathCreateMutable(); CGMutablePathRef theSecondPath = CGPathCreateMutable(); - CGAffineTransform transformation = CGAffineTransformIdentity; + CGAffineTransform transformation = self.options.affineTransform; CGPathMoveToPoint(theFirstPath, &transformation, 200, 35); CGPathAddLineToPoint(theFirstPath, &transformation, 165, 100); diff --git a/tests/testapps/CGCatalog/CGCatalog/CGPathAddQuadCurveToPointViewController.m b/tests/testapps/CGCatalog/CGCatalog/CGPathAddQuadCurveToPointViewController.m index 0bba1d829c..6272023973 100644 --- a/tests/testapps/CGCatalog/CGCatalog/CGPathAddQuadCurveToPointViewController.m +++ b/tests/testapps/CGCatalog/CGCatalog/CGPathAddQuadCurveToPointViewController.m @@ -35,7 +35,7 @@ - (void)loadView { CGContextSetStrokeColorWithColor(currentContext, self.options.lineColor); CGContextSetLineDash(currentContext, self.options.linePhase, self.options.lineDashPattern, self.options.lineDashCount); - CGAffineTransform transformation = CGAffineTransformIdentity; + CGAffineTransform transformation = self.options.affineTransform; CGMutablePathRef thePath = CGPathCreateMutable(); diff --git a/tests/testapps/CGCatalog/CGCatalog/CGPathAddRectViewController.m b/tests/testapps/CGCatalog/CGCatalog/CGPathAddRectViewController.m index b8813c98cc..315b43b5b9 100644 --- a/tests/testapps/CGCatalog/CGCatalog/CGPathAddRectViewController.m +++ b/tests/testapps/CGCatalog/CGCatalog/CGPathAddRectViewController.m @@ -37,7 +37,7 @@ - (void)loadView { CGMutablePathRef thePath = CGPathCreateMutable(); - CGAffineTransform transformation = CGAffineTransformIdentity; + CGAffineTransform transformation = self.options.affineTransform; CGPathMoveToPoint(thePath, &transformation, 50, 50); CGPathAddLineToPoint(thePath, &transformation, 100, 100); diff --git a/tests/testapps/CGCatalog/CGCatalog/CGPathAddRoundedRectViewController.m b/tests/testapps/CGCatalog/CGCatalog/CGPathAddRoundedRectViewController.m index b1fcbe40a9..ba00658d22 100644 --- a/tests/testapps/CGCatalog/CGCatalog/CGPathAddRoundedRectViewController.m +++ b/tests/testapps/CGCatalog/CGCatalog/CGPathAddRoundedRectViewController.m @@ -36,7 +36,7 @@ - (void)loadView { CGContextSetStrokeColorWithColor(currentContext, self.options.lineColor); CGContextSetLineDash(currentContext, self.options.linePhase, self.options.lineDashPattern, self.options.lineDashCount); - CGAffineTransform transformation = CGAffineTransformIdentity; + CGAffineTransform transformation = self.options.affineTransform; CGMutablePathRef thepath = CGPathCreateMutable(); CGPathMoveToPoint(thepath, &transformation, 75, 100); diff --git a/tests/testapps/CGCatalog/CGCatalog/CGPathCloseSubpathViewController.m b/tests/testapps/CGCatalog/CGCatalog/CGPathCloseSubpathViewController.m index 5f77084e4c..b16c445dfc 100644 --- a/tests/testapps/CGCatalog/CGCatalog/CGPathCloseSubpathViewController.m +++ b/tests/testapps/CGCatalog/CGCatalog/CGPathCloseSubpathViewController.m @@ -35,7 +35,7 @@ - (void)loadView { CGContextSetStrokeColorWithColor(currentContext, self.options.lineColor); CGContextSetLineDash(currentContext, self.options.linePhase, self.options.lineDashPattern, self.options.lineDashCount); - CGAffineTransform transformation = CGAffineTransformIdentity; + CGAffineTransform transformation = self.options.affineTransform; CGMutablePathRef thePath = CGPathCreateMutable(); CGPathMoveToPoint(thePath, &transformation, 50, 50); diff --git a/tests/testapps/CGCatalog/CGCatalog/CGPathContainsPointViewController.m b/tests/testapps/CGCatalog/CGCatalog/CGPathContainsPointViewController.m index 6dd04e177f..7aa41b35b3 100644 --- a/tests/testapps/CGCatalog/CGCatalog/CGPathContainsPointViewController.m +++ b/tests/testapps/CGCatalog/CGCatalog/CGPathContainsPointViewController.m @@ -51,7 +51,7 @@ - (void)loadView { CGContextSetStrokeColorWithColor(currentContext, weakSelf.options.lineColor); CGContextSetLineDash(currentContext, weakSelf.options.linePhase, weakSelf.options.lineDashPattern, weakSelf.options.lineDashCount); - CGAffineTransform transformation = CGAffineTransformIdentity; + CGAffineTransform transformation = self.options.affineTransform; weakSelf.containingPath = CGPathCreateMutable(); CGPathMoveToPoint(weakSelf.containingPath, &transformation, 200, 35); @@ -66,7 +66,7 @@ - (void)loadView { CGPathAddLineToPoint(weakSelf.containingPath, &transformation, 235, 100); // Unnecessary as close subpath will finish this line off but for the sake of consistency, have this here. - CGPathAddLineToPoint(weakSelf.containingPath, NULL, 200, 35); + CGPathAddLineToPoint(weakSelf.containingPath, &transformation, 200, 35); CGPathCloseSubpath(weakSelf.containingPath); CGContextAddPath(currentContext, weakSelf.containingPath); diff --git a/tests/testapps/CGCatalog/CGCatalog/CGPathGetBoundingBoxViewController.m b/tests/testapps/CGCatalog/CGCatalog/CGPathGetBoundingBoxViewController.m index 241c72baca..7ddf579a4e 100644 --- a/tests/testapps/CGCatalog/CGCatalog/CGPathGetBoundingBoxViewController.m +++ b/tests/testapps/CGCatalog/CGCatalog/CGPathGetBoundingBoxViewController.m @@ -35,7 +35,7 @@ - (void)loadView { CGContextSetStrokeColorWithColor(currentContext, self.options.lineColor); CGContextSetLineDash(currentContext, self.options.linePhase, self.options.lineDashPattern, self.options.lineDashCount); - CGAffineTransform transformation = CGAffineTransformIdentity; + CGAffineTransform transformation = self.options.affineTransform; CGMutablePathRef thepath = CGPathCreateMutable(); CGPathMoveToPoint(thepath, &transformation, 200, 35); diff --git a/tests/testapps/CGCatalog/CGCatalog/Samples/CGContextNewTestsController.m b/tests/testapps/CGCatalog/CGCatalog/Samples/CGContextNewTestsController.m index 778ffc3f5e..bb8a4dfa39 100644 --- a/tests/testapps/CGCatalog/CGCatalog/Samples/CGContextNewTestsController.m +++ b/tests/testapps/CGCatalog/CGCatalog/Samples/CGContextNewTestsController.m @@ -42,12 +42,14 @@ @interface CGContextNewTestsController () *)touches withEvent:(UIEvent*)event { [self.view endEditing:YES]; } +- (void)refreshTransformText { + NSNumberFormatter* formatter = [[NSNumberFormatter alloc] init]; + formatter.numberStyle = NSNumberFormatterDecimalStyle; + [formatter setMaximumFractionDigits:2]; + NSMutableString* transforamtionText = + [NSString stringWithFormat:@"%@, %@, %@, %@, %@, %@", + [formatter stringFromNumber:[NSNumber numberWithFloat:self.affineTransform.a]], + [formatter stringFromNumber:[NSNumber numberWithFloat:self.affineTransform.b]], + [formatter stringFromNumber:[NSNumber numberWithFloat:self.affineTransform.c]], + [formatter stringFromNumber:[NSNumber numberWithFloat:self.affineTransform.d]], + [formatter stringFromNumber:[NSNumber numberWithFloat:self.affineTransform.tx]], + [formatter stringFromNumber:[NSNumber numberWithFloat:self.affineTransform.ty]]]; + + [self.affineTransformText setText:transforamtionText]; + [self createTransformFromTextBoxes]; +} + +- (void)rotateRight:(UIButton*)sender { + self.affineTransform = CGAffineTransformRotate(self.affineTransform, M_PI / 10); + [self refreshTransformText]; +} + +- (void)rotateLeft:(UIButton*)sender { + self.affineTransform = CGAffineTransformRotate(self.affineTransform, -1 * M_PI / 10); + [self refreshTransformText]; +} + +- (void)moveRight:(UIButton*)sender { + self.affineTransform = CGAffineTransformTranslate(self.affineTransform, 10, 0); + [self refreshTransformText]; +} + +- (void)moveLeft:(UIButton*)sender { + self.affineTransform = CGAffineTransformTranslate(self.affineTransform, -10, 0); + [self refreshTransformText]; +} + +- (void)moveUp:(UIButton*)sender { + self.affineTransform = CGAffineTransformTranslate(self.affineTransform, 0, -10); + [self refreshTransformText]; +} + +- (void)moveDown:(UIButton*)sender { + self.affineTransform = CGAffineTransformTranslate(self.affineTransform, 0, 10); + [self refreshTransformText]; +} + - (void)loadView { [super loadView]; [self.view setBackgroundColor:[UIColor clearColor]]; UILabel* lineWidthText = [[UILabel alloc] initWithFrame:CGRectMake(0, 60, 100, 40)]; [lineWidthText setBackgroundColor:[UIColor whiteColor]]; + [lineWidthText setBackgroundColor:[UIColor whiteColor]]; [lineWidthText setText:@"LineWidth:"]; [self.view addSubview:lineWidthText]; @@ -223,6 +312,66 @@ - (void)loadView { [self.dashPatternText addTarget:self action:@selector(dashPatternCallback:) forControlEvents:UIControlEventEditingChanged]; [self.view addSubview:self.dashPatternText]; + UILabel* transformText = [[UILabel alloc] initWithFrame:CGRectMake(0, 140, 150, 40)]; + [transformText setBackgroundColor:[UIColor whiteColor]]; + [transformText setText:@"Affine Transform:"]; + [self.view addSubview:transformText]; + + self.affineTransformText = [[UITextField alloc] initWithFrame:CGRectMake(150, 140, 250, 40)]; + [self.affineTransformText setBackgroundColor:[UIColor whiteColor]]; + [self.affineTransformText setText:@"1.0, 0.0, 0.0, 1.0, 0.0, 0.0"]; + [self.affineTransformText addTarget:self action:@selector(affineTransformCallback:) forControlEvents:UIControlEventEditingChanged]; + [self.view addSubview:self.affineTransformText]; + + UIButton* rotateRightButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [rotateRightButton setBackgroundColor:[UIColor whiteColor]]; + [rotateRightButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; + [rotateRightButton addTarget:self action:@selector(rotateRight:) forControlEvents:UIControlEventTouchUpInside]; + rotateRightButton.frame = CGRectMake(0, 180, 50, 30); + [rotateRightButton setTitle:@"RR 3" forState:UIControlStateNormal]; + [self.view addSubview:rotateRightButton]; + + UIButton* rotateLeftButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [rotateLeftButton setBackgroundColor:[UIColor whiteColor]]; + [rotateLeftButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; + [rotateLeftButton addTarget:self action:@selector(rotateLeft:) forControlEvents:UIControlEventTouchUpInside]; + rotateLeftButton.frame = CGRectMake(50, 180, 50, 30); + [rotateLeftButton setTitle:@"RL 3" forState:UIControlStateNormal]; + [self.view addSubview:rotateLeftButton]; + + UIButton* moveRightButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [moveRightButton setBackgroundColor:[UIColor whiteColor]]; + [moveRightButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; + [moveRightButton addTarget:self action:@selector(moveRight:) forControlEvents:UIControlEventTouchUpInside]; + moveRightButton.frame = CGRectMake(100, 180, 60, 30); + [moveRightButton setTitle:@"MR 10" forState:UIControlStateNormal]; + [self.view addSubview:moveRightButton]; + + UIButton* moveLeftButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [moveLeftButton setBackgroundColor:[UIColor whiteColor]]; + [moveLeftButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; + [moveLeftButton addTarget:self action:@selector(moveLeft:) forControlEvents:UIControlEventTouchUpInside]; + moveLeftButton.frame = CGRectMake(160, 180, 60, 30); + [moveLeftButton setTitle:@"ML 10" forState:UIControlStateNormal]; + [self.view addSubview:moveLeftButton]; + + UIButton* moveUpButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [moveUpButton setBackgroundColor:[UIColor whiteColor]]; + [moveUpButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; + [moveUpButton addTarget:self action:@selector(moveUp:) forControlEvents:UIControlEventTouchUpInside]; + moveUpButton.frame = CGRectMake(220, 180, 60, 30); + [moveUpButton setTitle:@"MU 10" forState:UIControlStateNormal]; + [self.view addSubview:moveUpButton]; + + UIButton* moveDownButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [moveDownButton setBackgroundColor:[UIColor whiteColor]]; + [moveDownButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; + [moveDownButton addTarget:self action:@selector(moveDown:) forControlEvents:UIControlEventTouchUpInside]; + moveDownButton.frame = CGRectMake(280, 180, 60, 30); + [moveDownButton setTitle:@"MD 10" forState:UIControlStateNormal]; + [self.view addSubview:moveDownButton]; + + [self createTransformFromTextBoxes]; [self createNewColorFromTextBoxes]; [self createLineWidthFromText:nil]; [self dashPatternCallback:nil]; @@ -233,7 +382,7 @@ - (void)loadView { [tableView setDataSource:self]; CGRect viewBounds = self.view.bounds; - CGRect newTableBounds = CGRectMake(0, 150, viewBounds.origin.x + viewBounds.size.width, viewBounds.origin.y + viewBounds.size.height); + CGRect newTableBounds = CGRectMake(0, 210, viewBounds.origin.x + viewBounds.size.width, viewBounds.origin.y + viewBounds.size.height); [tableView setFrame:newTableBounds]; [self.view addSubview:tableView]; } @@ -248,7 +397,8 @@ - (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*) fillColor:self.lineColor lineDashPattern:self.dashComponents linePhase:self.dashPhase - dashCount:self.dashCount]; + dashCount:self.dashCount + transform:self.affineTransform]; [self.navigationController pushViewController:[[self.samples[indexPath.row].class alloc] initWithDrawingOptions:options] animated:YES]; } diff --git a/tests/unittests/CoreGraphics/CGContextTests.mm b/tests/unittests/CoreGraphics/CGContextTests.mm index 30db606df1..59cba2f2e1 100644 --- a/tests/unittests/CoreGraphics/CGContextTests.mm +++ b/tests/unittests/CoreGraphics/CGContextTests.mm @@ -78,7 +78,7 @@ void cgContextPathApplierFunction(void* info, const CGPathElement* element) { [result addObject:@{ kTypeKey : @(element->type), kPointsKey : points }]; } -inline bool operator==(const CGPoint& lhs, const CGPoint& rhs) { +static inline bool operator==(const CGPoint& lhs, const CGPoint& rhs) { return ((std::abs(lhs.x - rhs.x) < 0.00001) && (std::abs(lhs.y - rhs.y) < 0.00001)); } diff --git a/tests/unittests/CoreGraphics/CGPathTests.mm b/tests/unittests/CoreGraphics/CGPathTests.mm index 7d737b8d25..3e94148e6e 100644 --- a/tests/unittests/CoreGraphics/CGPathTests.mm +++ b/tests/unittests/CoreGraphics/CGPathTests.mm @@ -465,7 +465,7 @@ CGPathRef newPathForRoundRect(CGRect rect, CGFloat radius) { EXPECT_FALSE(test); } -TEST(CGPath, CGPathContainsPointShoulders) { +DISABLED_TEST(CGPath, CGPathContainsPointShoulders) { CGFloat originX = 10.0f; CGFloat originY = 20.0f; CGFloat pathWidth = 100.0f; @@ -502,7 +502,7 @@ CGPathRef newPathForRoundRect(CGRect rect, CGFloat radius) { EXPECT_TRUE(test); } -TEST(CGPath, CGPathContainsPointWithTransform) { +DISABLED_TEST(CGPath, CGPathContainsPointWithTransform) { CGFloat originX = 10.0f; CGFloat originY = 20.0f; CGFloat pathWidth = 100.0f; From 4d4c8269c9776377967f124b54efe730e44c4526 Mon Sep 17 00:00:00 2001 From: Hank Fox Date: Mon, 21 Nov 2016 15:14:28 -0800 Subject: [PATCH 4/8] Fixing UI and other things. --- Frameworks/CoreGraphics/CGPath.mm | 2 +- .../Samples/CGContextNewTestsController.m | 31 ++++++------------- 2 files changed, 11 insertions(+), 22 deletions(-) diff --git a/Frameworks/CoreGraphics/CGPath.mm b/Frameworks/CoreGraphics/CGPath.mm index 594ce7a23e..19590a28c7 100644 --- a/Frameworks/CoreGraphics/CGPath.mm +++ b/Frameworks/CoreGraphics/CGPath.mm @@ -82,7 +82,7 @@ void SetStartingPoint(CGPoint newPoint) { startingPoint = newPoint; } - const void SetLastTransform(const CGAffineTransform* transform) { + void SetLastTransform(const CGAffineTransform* transform) { if (transform) { lastTransform = *transform; } else { diff --git a/tests/testapps/CGCatalog/CGCatalog/Samples/CGContextNewTestsController.m b/tests/testapps/CGCatalog/CGCatalog/Samples/CGContextNewTestsController.m index bb8a4dfa39..853b565a22 100644 --- a/tests/testapps/CGCatalog/CGCatalog/Samples/CGContextNewTestsController.m +++ b/tests/testapps/CGCatalog/CGCatalog/Samples/CGContextNewTestsController.m @@ -71,18 +71,6 @@ - (NSArray*)samples { [CGContextSampleRow row:@"CGPathAddArc" class:[CGPathAddArcViewController class]], [CGContextSampleRow row:@"CGPathAddArcToPoint" class:[CGPathAddArcToPointViewController class]], [CGContextSampleRow row:@"CGPathAddRoundedRect" class:[CGPathAddRoundedRectViewController class]], - [CGContextSampleRow row:@"" class:[CGPathAddRoundedRectViewController class]], - [CGContextSampleRow row:@"" class:[CGPathAddRoundedRectViewController class]], - [CGContextSampleRow row:@"" class:[CGPathAddRoundedRectViewController class]], - [CGContextSampleRow row:@"" class:[CGPathAddRoundedRectViewController class]], - [CGContextSampleRow row:@"" class:[CGPathAddRoundedRectViewController class]], - [CGContextSampleRow row:@"" class:[CGPathAddRoundedRectViewController class]], - [CGContextSampleRow row:@"" class:[CGPathAddRoundedRectViewController class]], - [CGContextSampleRow row:@"" class:[CGPathAddRoundedRectViewController class]], - [CGContextSampleRow row:@"" class:[CGPathAddRoundedRectViewController class]], - [CGContextSampleRow row:@"" class:[CGPathAddRoundedRectViewController class]], - [CGContextSampleRow row:@"" class:[CGPathAddRoundedRectViewController class]], - [CGContextSampleRow row:@"" class:[CGPathAddRoundedRectViewController class]], ]; } return _samples; @@ -227,12 +215,12 @@ - (void)refreshTransformText { } - (void)rotateRight:(UIButton*)sender { - self.affineTransform = CGAffineTransformRotate(self.affineTransform, M_PI / 10); + self.affineTransform = CGAffineTransformRotate(self.affineTransform, M_PI / 36); [self refreshTransformText]; } - (void)rotateLeft:(UIButton*)sender { - self.affineTransform = CGAffineTransformRotate(self.affineTransform, -1 * M_PI / 10); + self.affineTransform = CGAffineTransformRotate(self.affineTransform, -1 * M_PI / 36); [self refreshTransformText]; } @@ -328,7 +316,7 @@ - (void)loadView { [rotateRightButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [rotateRightButton addTarget:self action:@selector(rotateRight:) forControlEvents:UIControlEventTouchUpInside]; rotateRightButton.frame = CGRectMake(0, 180, 50, 30); - [rotateRightButton setTitle:@"RR 3" forState:UIControlStateNormal]; + [rotateRightButton setTitle:@"+5\u00B0" forState:UIControlStateNormal]; [self.view addSubview:rotateRightButton]; UIButton* rotateLeftButton = [UIButton buttonWithType:UIButtonTypeCustom]; @@ -336,7 +324,7 @@ - (void)loadView { [rotateLeftButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [rotateLeftButton addTarget:self action:@selector(rotateLeft:) forControlEvents:UIControlEventTouchUpInside]; rotateLeftButton.frame = CGRectMake(50, 180, 50, 30); - [rotateLeftButton setTitle:@"RL 3" forState:UIControlStateNormal]; + [rotateLeftButton setTitle:@"-5\u00B0" forState:UIControlStateNormal]; [self.view addSubview:rotateLeftButton]; UIButton* moveRightButton = [UIButton buttonWithType:UIButtonTypeCustom]; @@ -344,7 +332,7 @@ - (void)loadView { [moveRightButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [moveRightButton addTarget:self action:@selector(moveRight:) forControlEvents:UIControlEventTouchUpInside]; moveRightButton.frame = CGRectMake(100, 180, 60, 30); - [moveRightButton setTitle:@"MR 10" forState:UIControlStateNormal]; + [moveRightButton setTitle:@"X+10" forState:UIControlStateNormal]; [self.view addSubview:moveRightButton]; UIButton* moveLeftButton = [UIButton buttonWithType:UIButtonTypeCustom]; @@ -352,7 +340,7 @@ - (void)loadView { [moveLeftButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [moveLeftButton addTarget:self action:@selector(moveLeft:) forControlEvents:UIControlEventTouchUpInside]; moveLeftButton.frame = CGRectMake(160, 180, 60, 30); - [moveLeftButton setTitle:@"ML 10" forState:UIControlStateNormal]; + [moveLeftButton setTitle:@"X-10" forState:UIControlStateNormal]; [self.view addSubview:moveLeftButton]; UIButton* moveUpButton = [UIButton buttonWithType:UIButtonTypeCustom]; @@ -360,7 +348,7 @@ - (void)loadView { [moveUpButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [moveUpButton addTarget:self action:@selector(moveUp:) forControlEvents:UIControlEventTouchUpInside]; moveUpButton.frame = CGRectMake(220, 180, 60, 30); - [moveUpButton setTitle:@"MU 10" forState:UIControlStateNormal]; + [moveUpButton setTitle:@"Y-10" forState:UIControlStateNormal]; [self.view addSubview:moveUpButton]; UIButton* moveDownButton = [UIButton buttonWithType:UIButtonTypeCustom]; @@ -368,7 +356,7 @@ - (void)loadView { [moveDownButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [moveDownButton addTarget:self action:@selector(moveDown:) forControlEvents:UIControlEventTouchUpInside]; moveDownButton.frame = CGRectMake(280, 180, 60, 30); - [moveDownButton setTitle:@"MD 10" forState:UIControlStateNormal]; + [moveDownButton setTitle:@"Y+10" forState:UIControlStateNormal]; [self.view addSubview:moveDownButton]; [self createTransformFromTextBoxes]; @@ -382,7 +370,8 @@ - (void)loadView { [tableView setDataSource:self]; CGRect viewBounds = self.view.bounds; - CGRect newTableBounds = CGRectMake(0, 210, viewBounds.origin.x + viewBounds.size.width, viewBounds.origin.y + viewBounds.size.height); + CGRect newTableBounds = + CGRectMake(0, 210, viewBounds.origin.x + viewBounds.size.width, viewBounds.origin.y + viewBounds.size.height - 260); [tableView setFrame:newTableBounds]; [self.view addSubview:tableView]; } From 0d4579cfe75b92bf5614244876c16bc417e3334e Mon Sep 17 00:00:00 2001 From: Hank Fox Date: Tue, 29 Nov 2016 11:57:19 -0800 Subject: [PATCH 5/8] Adding comments on arc math and updating cpputils --- Frameworks/CoreGraphics/CGPath.mm | 47 ++++++++++++++++--------------- Frameworks/include/CppUtils.h | 7 +++++ 2 files changed, 31 insertions(+), 23 deletions(-) diff --git a/Frameworks/CoreGraphics/CGPath.mm b/Frameworks/CoreGraphics/CGPath.mm index 19590a28c7..1f1c08ac42 100644 --- a/Frameworks/CoreGraphics/CGPath.mm +++ b/Frameworks/CoreGraphics/CGPath.mm @@ -31,6 +31,7 @@ #include #import +#import static const wchar_t* TAG = L"CGPath"; @@ -159,7 +160,7 @@ HRESULT InitializeGeometries() { return S_OK; } - HRESULT SimplifyGeometryToPathWithTransformation(ComPtr geometry, const CGAffineTransform* transform) { + HRESULT AddGeometryToPathWithTransformation(ComPtr geometry, const CGAffineTransform* transform) { RETURN_IF_FAILED(ClosePath()); RETURN_IF_FAILED(PreparePathForEditing()); @@ -276,23 +277,18 @@ void CGPathAddLineToPoint(CGMutablePathRef path, const CGAffineTransform* transf path->SetCurrentPoint(pt); } -static inline bool _affineTransformEquals(const CGAffineTransform original, const CGAffineTransform compare) { - return (original.a != compare.a) && (original.b == compare.b) && (original.c == compare.c) && (original.d == compare.d) && - (original.tx == compare.tx) && (original.ty == compare.ty); -} - static inline CGPoint _getInvertedCurrentPointOfPath(CGPathRef path) { CGPoint point = path->GetCurrentPoint(); - if (!_affineTransformEquals(*path->GetLastTransform(), CGAffineTransformIdentity)) { + if (!(*path->GetLastTransform() == CGAffineTransformIdentity)) { point = CGPointApplyAffineTransform(point, CGAffineTransformInvert(*path->GetLastTransform())); } return point; } static HRESULT _createPathReadyForFigure(CGPathRef previousPath, + CGPoint startPoint, ID2D1PathGeometry** pathGeometry, - ID2D1GeometrySink** geometrySink, - CGPoint startPoint) { + ID2D1GeometrySink** geometrySink) { ComPtr factory; RETURN_IF_FAILED(_CGGetD2DFactory(&factory)); RETURN_IF_FAILED(factory->CreatePathGeometry(pathGeometry)); @@ -317,13 +313,14 @@ void CGPathAddArcToPoint( CGPoint invertedPoint = _getInvertedCurrentPointOfPath(path); + // Get the distance to the vertex of the angle created by the tangent lines. CGFloat dx1 = x1 - invertedPoint.x; CGFloat dy1 = y1 - invertedPoint.y; CGFloat dx2 = x1 - x2; CGFloat dy2 = y1 - y2; - // Normalize the angles we're working with. + // Normalize the angles of the tangent lines. CGFloat startAngle = fmod(atan2(dy1, dx1), 2 * M_PI); CGFloat endAngle = fmod(atan2(dy2, dx2), 2 * M_PI); if (startAngle < 0) { @@ -333,11 +330,13 @@ void CGPathAddArcToPoint( endAngle += M_PI * 2; } + // Calculate the angle of the bisector between the tangent line's angles. CGFloat bisector = (endAngle - startAngle) / 2; - // tanLength is the distance to the point on the circle from the tangent line. + // tanLength is the distance to the point on the circle from the tangent line starting at the vertex point x1,y1. CGFloat tanLength = abs(radius / tan(bisector)); + // Calculate the tangent points on the circle from the tangent lines. These are the start and end points required by D2D. CGFloat tanPointAx = x1 - (tanLength * cos(startAngle)); CGFloat tanPointAy = y1 - (tanLength * sin(startAngle)); CGFloat tanPointBx = x1 - (tanLength * cos(endAngle)); @@ -346,13 +345,15 @@ void CGPathAddArcToPoint( CGPoint endPoint = CGPointMake(tanPointBx, tanPointBy); const D2D1_POINT_2F endPointD2D = _CGPointToD2D_F(endPoint); + // Determine the direction that the arc will be drawn in. This will always be the shorter angle which is why it's calculated based off + // the startAngle + 180 degrees or PI radians. int sweepSign = 1; if (startAngle > endAngle) { sweepSign = -1; } D2D1_SWEEP_DIRECTION sweepDirection = { startAngle + (M_PI * sweepSign) < endAngle ? D2D1_SWEEP_DIRECTION_CLOCKWISE : D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE }; - + // Set up the D2D arc segment. const D2D1_SIZE_F radiusD2D = { radius, radius }; FLOAT rotationAngle = bisector * 2; D2D1_ARC_SIZE arcSize = D2D1_ARC_SIZE_SMALL; @@ -360,12 +361,12 @@ void CGPathAddArcToPoint( ComPtr newPath; ComPtr newSink; - FAIL_FAST_IF_FAILED(_createPathReadyForFigure(path, &newPath, &newSink, CGPointMake(tanPointAx, tanPointAy))); + FAIL_FAST_IF_FAILED(_createPathReadyForFigure(path, CGPointMake(tanPointAx, tanPointAy), &newPath, &newSink)); newSink->AddArc(arcSegment); newSink->EndFigure(D2D1_FIGURE_END_OPEN); FAIL_FAST_IF_FAILED(newSink->Close()); - FAIL_FAST_IF_FAILED(path->SimplifyGeometryToPathWithTransformation(newPath, transform)); + FAIL_FAST_IF_FAILED(path->AddGeometryToPathWithTransformation(newPath, transform)); if (transform) { endPoint = CGPointApplyAffineTransform(endPoint, *transform); @@ -410,13 +411,13 @@ void CGPathAddArc(CGMutablePathRef path, ComPtr newPath; ComPtr newSink; - FAIL_FAST_IF_FAILED(_createPathReadyForFigure(path, &newPath, &newSink, startPoint)); + FAIL_FAST_IF_FAILED(_createPathReadyForFigure(path, startPoint, &newPath, &newSink)); newSink->AddArc(arcSegment); newSink->EndFigure(D2D1_FIGURE_END_OPEN); FAIL_FAST_IF_FAILED(newSink->Close()); - FAIL_FAST_IF_FAILED(path->SimplifyGeometryToPathWithTransformation(newPath, transform)); + FAIL_FAST_IF_FAILED(path->AddGeometryToPathWithTransformation(newPath, transform)); if (transform) { endPoint = CGPointApplyAffineTransform(endPoint, *transform); @@ -475,7 +476,7 @@ void CGPathAddPath(CGMutablePathRef path, const CGAffineTransform* transform, CG // Close the path being added. FAIL_FAST_IF_FAILED(toAdd->ClosePath()); - FAIL_FAST_IF_FAILED(path->SimplifyGeometryToPathWithTransformation(toAdd->GetPathGeometry(), transform)); + FAIL_FAST_IF_FAILED(path->AddGeometryToPathWithTransformation(toAdd->GetPathGeometry(), transform)); CGPoint currentPoint = toAdd->GetCurrentPoint(); CGPoint startingPoint = toAdd->GetStartingPoint(); @@ -505,7 +506,7 @@ void CGPathAddEllipseInRect(CGMutablePathRef path, const CGAffineTransform* tran FAIL_FAST_IF_FAILED(factory->CreateEllipseGeometry(&ellipse, &ellipseGeometry)); - FAIL_FAST_IF_FAILED(path->SimplifyGeometryToPathWithTransformation(ellipseGeometry, transform)); + FAIL_FAST_IF_FAILED(path->AddGeometryToPathWithTransformation(ellipseGeometry, transform)); path->SetLastTransform(transform); } @@ -594,12 +595,12 @@ void CGPathAddQuadCurveToPoint(CGMutablePathRef path, const CGAffineTransform* t ComPtr newPath; ComPtr newSink; - FAIL_FAST_IF_FAILED(_createPathReadyForFigure(path, &newPath, &newSink, _getInvertedCurrentPointOfPath(path))); + FAIL_FAST_IF_FAILED(_createPathReadyForFigure(path, _getInvertedCurrentPointOfPath(path), &newPath, &newSink)); newSink->AddQuadraticBezier(D2D1::QuadraticBezierSegment(_CGPointToD2D_F(controlPoint), _CGPointToD2D_F(endPoint))); newSink->EndFigure(D2D1_FIGURE_END_OPEN); FAIL_FAST_IF_FAILED(newSink->Close()); - FAIL_FAST_IF_FAILED(path->SimplifyGeometryToPathWithTransformation(newPath, transform)); + FAIL_FAST_IF_FAILED(path->AddGeometryToPathWithTransformation(newPath, transform)); if (transform) { endPoint = CGPointApplyAffineTransform(endPoint, *transform); @@ -628,12 +629,12 @@ void CGPathAddCurveToPoint(CGMutablePathRef path, ComPtr newPath; ComPtr newSink; - FAIL_FAST_IF_FAILED(_createPathReadyForFigure(path, &newPath, &newSink, _getInvertedCurrentPointOfPath(path))); + FAIL_FAST_IF_FAILED(_createPathReadyForFigure(path, _getInvertedCurrentPointOfPath(path), &newPath, &newSink)); newSink->AddBezier(D2D1::BezierSegment(_CGPointToD2D_F(controlPoint1), _CGPointToD2D_F(controlPoint2), _CGPointToD2D_F(endPoint))); newSink->EndFigure(D2D1_FIGURE_END_OPEN); FAIL_FAST_IF_FAILED(newSink->Close()); - FAIL_FAST_IF_FAILED(path->SimplifyGeometryToPathWithTransformation(newPath, transform)); + FAIL_FAST_IF_FAILED(path->AddGeometryToPathWithTransformation(newPath, transform)); if (transform) { endPoint = CGPointApplyAffineTransform(endPoint, *transform); @@ -704,7 +705,7 @@ void CGPathAddRoundedRect( FAIL_FAST_IF_FAILED(factory->CreateRoundedRectangleGeometry(&roundedRectangle, &rectangleGeometry)); - FAIL_FAST_IF_FAILED(path->SimplifyGeometryToPathWithTransformation(rectangleGeometry, transform)); + FAIL_FAST_IF_FAILED(path->AddGeometryToPathWithTransformation(rectangleGeometry, transform)); path->SetLastTransform(transform); } diff --git a/Frameworks/include/CppUtils.h b/Frameworks/include/CppUtils.h index 4e4b9b26c3..0f2224a642 100644 --- a/Frameworks/include/CppUtils.h +++ b/Frameworks/include/CppUtils.h @@ -47,4 +47,11 @@ bool operator==(const CGRect& lhs, const CGRect& rhs) { #pragma endregion +#pragma region CGAffineTransform +bool operator==(const CGAffineTransform& lhs, const CGAffineTransform& rhs) { + return (lhs.a != rhs.a) && (lhs.b == rhs.b) && (lhs.c == rhs.c) && (lhs.d == rhs.d) && (lhs.tx == rhs.tx) && (lhs.ty == rhs.ty); +} + +#pragma endregion + #endif From 3628cc96afb402e1c3db60501b3a226ad878cfa1 Mon Sep 17 00:00:00 2001 From: Hank Fox Date: Tue, 29 Nov 2016 12:54:13 -0800 Subject: [PATCH 6/8] Use CGAffineTransform equality function instead of defining our own. --- Frameworks/CoreGraphics/CGPath.mm | 2 +- Frameworks/include/CppUtils.h | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/Frameworks/CoreGraphics/CGPath.mm b/Frameworks/CoreGraphics/CGPath.mm index 1f1c08ac42..45e7490793 100644 --- a/Frameworks/CoreGraphics/CGPath.mm +++ b/Frameworks/CoreGraphics/CGPath.mm @@ -279,7 +279,7 @@ void CGPathAddLineToPoint(CGMutablePathRef path, const CGAffineTransform* transf static inline CGPoint _getInvertedCurrentPointOfPath(CGPathRef path) { CGPoint point = path->GetCurrentPoint(); - if (!(*path->GetLastTransform() == CGAffineTransformIdentity)) { + if (!CGAffineTransformEqualToTransform(*path->GetLastTransform(), CGAffineTransformIdentity)) { point = CGPointApplyAffineTransform(point, CGAffineTransformInvert(*path->GetLastTransform())); } return point; diff --git a/Frameworks/include/CppUtils.h b/Frameworks/include/CppUtils.h index 0f2224a642..4e4b9b26c3 100644 --- a/Frameworks/include/CppUtils.h +++ b/Frameworks/include/CppUtils.h @@ -47,11 +47,4 @@ bool operator==(const CGRect& lhs, const CGRect& rhs) { #pragma endregion -#pragma region CGAffineTransform -bool operator==(const CGAffineTransform& lhs, const CGAffineTransform& rhs) { - return (lhs.a != rhs.a) && (lhs.b == rhs.b) && (lhs.c == rhs.c) && (lhs.d == rhs.d) && (lhs.tx == rhs.tx) && (lhs.ty == rhs.ty); -} - -#pragma endregion - #endif From 296874339b784edfd9c3ec5aad8227ebf40c787e Mon Sep 17 00:00:00 2001 From: Hank Fox Date: Wed, 30 Nov 2016 11:04:04 -0800 Subject: [PATCH 7/8] Fix const getter functions, reorder out pointer arguments --- Frameworks/CoreGraphics/CGPath.mm | 35 +++++++++++++------------------ 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/Frameworks/CoreGraphics/CGPath.mm b/Frameworks/CoreGraphics/CGPath.mm index 45e7490793..65abc3c7d3 100644 --- a/Frameworks/CoreGraphics/CGPath.mm +++ b/Frameworks/CoreGraphics/CGPath.mm @@ -59,19 +59,19 @@ static inline CGPoint __CreateCGPointWithTransform(CGFloat x, CGFloat y, const C __CGPath() : figureClosed(true), lastTransform(CGAffineTransformIdentity) { } - ComPtr GetPathGeometry() { + ComPtr GetPathGeometry() const { return pathGeometry; } - ComPtr GetGeometrySink() { + ComPtr GetGeometrySink() const { return geometrySink; } - CGPoint GetCurrentPoint() { + CGPoint GetCurrentPoint() const { return currentPoint; } - CGPoint GetStartingPoint() { + CGPoint GetStartingPoint() const { return startingPoint; } @@ -91,7 +91,7 @@ void SetLastTransform(const CGAffineTransform* transform) { } } - const CGAffineTransform* GetLastTransform() { + const CGAffineTransform* GetLastTransform() const { return &lastTransform; } @@ -160,7 +160,7 @@ HRESULT InitializeGeometries() { return S_OK; } - HRESULT AddGeometryToPathWithTransformation(ComPtr geometry, const CGAffineTransform* transform) { + HRESULT AddGeometryToPathWithTransformation(const ID2D1Geometry* geometry, const CGAffineTransform* transform) { RETURN_IF_FAILED(ClosePath()); RETURN_IF_FAILED(PreparePathForEditing()); @@ -170,6 +170,8 @@ HRESULT AddGeometryToPathWithTransformation(ComPtr geometry, cons } RETURN_IF_FAILED( geometry->Simplify(D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES, &transformation, GetGeometrySink().Get())); + + SetLastTransform(transform); return S_OK; } }; @@ -366,12 +368,11 @@ void CGPathAddArcToPoint( newSink->EndFigure(D2D1_FIGURE_END_OPEN); FAIL_FAST_IF_FAILED(newSink->Close()); - FAIL_FAST_IF_FAILED(path->AddGeometryToPathWithTransformation(newPath, transform)); + FAIL_FAST_IF_FAILED(path->AddGeometryToPathWithTransformation(newPath.Get(), transform)); if (transform) { endPoint = CGPointApplyAffineTransform(endPoint, *transform); } - path->SetLastTransform(transform); path->SetCurrentPoint(endPoint); } @@ -417,12 +418,11 @@ void CGPathAddArc(CGMutablePathRef path, newSink->EndFigure(D2D1_FIGURE_END_OPEN); FAIL_FAST_IF_FAILED(newSink->Close()); - FAIL_FAST_IF_FAILED(path->AddGeometryToPathWithTransformation(newPath, transform)); + FAIL_FAST_IF_FAILED(path->AddGeometryToPathWithTransformation(newPath.Get(), transform)); if (transform) { endPoint = CGPointApplyAffineTransform(endPoint, *transform); } - path->SetLastTransform(transform); path->SetCurrentPoint(endPoint); } @@ -476,7 +476,7 @@ void CGPathAddPath(CGMutablePathRef path, const CGAffineTransform* transform, CG // Close the path being added. FAIL_FAST_IF_FAILED(toAdd->ClosePath()); - FAIL_FAST_IF_FAILED(path->AddGeometryToPathWithTransformation(toAdd->GetPathGeometry(), transform)); + FAIL_FAST_IF_FAILED(path->AddGeometryToPathWithTransformation(toAdd->GetPathGeometry().Get(), transform)); CGPoint currentPoint = toAdd->GetCurrentPoint(); CGPoint startingPoint = toAdd->GetStartingPoint(); @@ -486,7 +486,6 @@ void CGPathAddPath(CGMutablePathRef path, const CGAffineTransform* transform, CG } path->SetStartingPoint(startingPoint); path->SetCurrentPoint(currentPoint); - path->SetLastTransform(transform); } /** @@ -506,8 +505,7 @@ void CGPathAddEllipseInRect(CGMutablePathRef path, const CGAffineTransform* tran FAIL_FAST_IF_FAILED(factory->CreateEllipseGeometry(&ellipse, &ellipseGeometry)); - FAIL_FAST_IF_FAILED(path->AddGeometryToPathWithTransformation(ellipseGeometry, transform)); - path->SetLastTransform(transform); + FAIL_FAST_IF_FAILED(path->AddGeometryToPathWithTransformation(ellipseGeometry.Get(), transform)); } /** @@ -600,13 +598,12 @@ void CGPathAddQuadCurveToPoint(CGMutablePathRef path, const CGAffineTransform* t newSink->EndFigure(D2D1_FIGURE_END_OPEN); FAIL_FAST_IF_FAILED(newSink->Close()); - FAIL_FAST_IF_FAILED(path->AddGeometryToPathWithTransformation(newPath, transform)); + FAIL_FAST_IF_FAILED(path->AddGeometryToPathWithTransformation(newPath.Get(), transform)); if (transform) { endPoint = CGPointApplyAffineTransform(endPoint, *transform); } path->SetCurrentPoint(endPoint); - path->SetLastTransform(transform); } /** @@ -634,13 +631,12 @@ void CGPathAddCurveToPoint(CGMutablePathRef path, newSink->EndFigure(D2D1_FIGURE_END_OPEN); FAIL_FAST_IF_FAILED(newSink->Close()); - FAIL_FAST_IF_FAILED(path->AddGeometryToPathWithTransformation(newPath, transform)); + FAIL_FAST_IF_FAILED(path->AddGeometryToPathWithTransformation(newPath.Get(), transform)); if (transform) { endPoint = CGPointApplyAffineTransform(endPoint, *transform); } path->SetCurrentPoint(endPoint); - path->SetLastTransform(transform); } /** @@ -705,8 +701,7 @@ void CGPathAddRoundedRect( FAIL_FAST_IF_FAILED(factory->CreateRoundedRectangleGeometry(&roundedRectangle, &rectangleGeometry)); - FAIL_FAST_IF_FAILED(path->AddGeometryToPathWithTransformation(rectangleGeometry, transform)); - path->SetLastTransform(transform); + FAIL_FAST_IF_FAILED(path->AddGeometryToPathWithTransformation(rectangleGeometry.Get(), transform)); } int _CGPathPointCountForElementType(CGPathElementType type) { From ce69c52e83c88df4de75c0e6ea1d78708c89ad09 Mon Sep 17 00:00:00 2001 From: Hank Fox Date: Wed, 30 Nov 2016 14:22:25 -0800 Subject: [PATCH 8/8] Fix failing coordinate tests due to stomped equality operator. --- Frameworks/include/CppUtils.h | 16 +++++++++++----- tests/unittests/CoreGraphics/CGContextTests.mm | 10 +--------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/Frameworks/include/CppUtils.h b/Frameworks/include/CppUtils.h index 4e4b9b26c3..6e27ade080 100644 --- a/Frameworks/include/CppUtils.h +++ b/Frameworks/include/CppUtils.h @@ -19,29 +19,35 @@ #ifdef __cplusplus +#import + #pragma region CFRange -bool operator==(const CFRange& lhs, const CFRange& rhs) { +inline bool operator==(const CFRange& lhs, const CFRange& rhs) { return lhs.location == rhs.location && lhs.length == rhs.length; } #pragma endregion #pragma region CGPoint -bool operator==(const CGPoint& lhs, const CGPoint& rhs) { - return lhs.x == rhs.x && lhs.y == rhs.y; +template +std::basic_ostream& operator<<(std::basic_ostream& os, const CGPoint& pt) { + return os << "{" << pt.x << ", " << pt.y << "}"; } +inline bool operator==(const CGPoint& lhs, const CGPoint& rhs) { + return ((std::abs(lhs.x - rhs.x) < 0.00001) && (std::abs(lhs.y - rhs.y) < 0.00001)); +} #pragma endregion #pragma region CGSize -bool operator==(const CGSize& lhs, const CGSize& rhs) { +inline bool operator==(const CGSize& lhs, const CGSize& rhs) { return lhs.width == rhs.width && lhs.height == rhs.height; } #pragma endregion #pragma region CGRect -bool operator==(const CGRect& lhs, const CGRect& rhs) { +inline bool operator==(const CGRect& lhs, const CGRect& rhs) { return lhs.origin == rhs.origin && lhs.size == rhs.size; } diff --git a/tests/unittests/CoreGraphics/CGContextTests.mm b/tests/unittests/CoreGraphics/CGContextTests.mm index 59cba2f2e1..22baf1d5f0 100644 --- a/tests/unittests/CoreGraphics/CGContextTests.mm +++ b/tests/unittests/CoreGraphics/CGContextTests.mm @@ -21,6 +21,7 @@ #import #import #import +#import #if TARGET_OS_WIN32 #include @@ -78,10 +79,6 @@ void cgContextPathApplierFunction(void* info, const CGPathElement* element) { [result addObject:@{ kTypeKey : @(element->type), kPointsKey : points }]; } -static inline bool operator==(const CGPoint& lhs, const CGPoint& rhs) { - return ((std::abs(lhs.x - rhs.x) < 0.00001) && (std::abs(lhs.y - rhs.y) < 0.00001)); -} - // Helper function that compares results from cgPathApplierFunction to expected results void cgContextPathCompare(NSArray* expected, NSArray* result) { ASSERT_EQ(expected.count, result.count) << "Counts do not match for expected and result"; @@ -280,11 +277,6 @@ void cgContextPathCompare(NSArray* expected, NSArray* result) { CGColorSpaceRelease(rgbColorSpace); } -template -std::basic_ostream& operator<<(std::basic_ostream& os, const CGPoint& pt) { - return os << "{" << pt.x << ", " << pt.y << "}"; -} - template std::basic_ostream& operator<<(std::basic_ostream& os, const CGAffineTransform& transform) { os << "[";