From cc31efafb9453af9d899499870b06644031f0762 Mon Sep 17 00:00:00 2001 From: Aaron DeGrow Date: Fri, 24 Jun 2016 14:59:13 -0400 Subject: [PATCH] Implemented CGContextSetPatternPhase Implemented CGContextSetPatternPhase using the translation portion of the pattern's transform matrix. Implements last item in Issue #524 --- Frameworks/CoreGraphics/CGContext.mm | 5 +- Frameworks/CoreGraphics/CGContextImpl.mm | 10 ++ Frameworks/include/CGContextImpl.h | 7 ++ build/CoreGraphics/dll/CoreGraphics.def | 1 + .../CoreGraphics.UnitTests.vcxproj | 4 +- include/CoreGraphics/CGContext.h | 2 +- .../Samples/CGCCGContextSetPatternPhase.m | 7 -- .../unittests/CoreGraphics/CGContextTests.mm | 101 ++++++++++++++++++ 8 files changed, 124 insertions(+), 13 deletions(-) diff --git a/Frameworks/CoreGraphics/CGContext.mm b/Frameworks/CoreGraphics/CGContext.mm index 0bd842cfab..87432a9bbf 100644 --- a/Frameworks/CoreGraphics/CGContext.mm +++ b/Frameworks/CoreGraphics/CGContext.mm @@ -93,11 +93,10 @@ void CGContextSetFillPattern(CGContextRef ctx, CGPatternRef pattern, const float } /** - @Status Stub + @Status Interoperable */ void CGContextSetPatternPhase(CGContextRef ctx, CGSize phase) { - UNIMPLEMENTED(); - TraceWarning(TAG, L"CGContextSetPatternPhase not implemented"); + return ctx->Backing()->CGContextSetPatternPhase(phase); } /** diff --git a/Frameworks/CoreGraphics/CGContextImpl.mm b/Frameworks/CoreGraphics/CGContextImpl.mm index 37d481790c..6f7190953b 100644 --- a/Frameworks/CoreGraphics/CGContextImpl.mm +++ b/Frameworks/CoreGraphics/CGContextImpl.mm @@ -400,6 +400,16 @@ } } +void CGContextImpl::CGContextSetPatternPhase(CGSize phase) { + if ([curState->curFillColorObject isKindOfClass:[CGPattern class]]) { + CGPattern* pattern = curState->curFillColorObject; + CGAffineTransform matrix = pattern->matrix; + matrix.tx += phase.width; + matrix.ty += phase.height; + pattern->matrix = matrix; + } +} + void CGContextImpl::CGContextSelectFont(char* name, float size, DWORD encoding) { // curState->curFont = [UIFont class]("fontWithName:size:", @name, size); curState->fontSize = size; diff --git a/Frameworks/include/CGContextImpl.h b/Frameworks/include/CGContextImpl.h index ca3f030eb1..8ad28fd6b3 100644 --- a/Frameworks/include/CGContextImpl.h +++ b/Frameworks/include/CGContextImpl.h @@ -15,6 +15,11 @@ //****************************************************************************** #pragma once + +#ifndef __CGCONTEXTIMPL_TEST_FRIENDS +#define __CGCONTEXTIMPL_TEST_FRIENDS +#endif + #include "CGContextInternal.h" #include "CoreGraphics/CGPath.h" @@ -53,6 +58,7 @@ typedef struct { #define MAX_CG_STATES 16 class CGContextImpl { +__CGCONTEXTIMPL_TEST_FRIENDS; protected: CGContextRef _rootContext; CGImageRef _imgDest; @@ -107,6 +113,7 @@ class CGContextImpl { virtual void CGContextSetStrokeColorWithColor(id color); virtual void CGContextSetFillColorWithColor(id color); virtual void CGContextSetFillColor(float* components); + virtual void CGContextSetPatternPhase(CGSize phase); virtual void CGContextSetFillPattern(CGPatternRef pattern, const float* components); virtual void CGContextSelectFont(char* name, float size, DWORD encoding); virtual void CGContextGetTextPosition(CGPoint* pos); diff --git a/build/CoreGraphics/dll/CoreGraphics.def b/build/CoreGraphics/dll/CoreGraphics.def index 36571acfd2..aa155313b0 100644 --- a/build/CoreGraphics/dll/CoreGraphics.def +++ b/build/CoreGraphics/dll/CoreGraphics.def @@ -215,6 +215,7 @@ LIBRARY CoreGraphics CGContextIsDirty CGContextReleaseLock CGContextSetDirty + CGContextGetBacking EbrCenterTextInRectVertically ; CGDataConsumer.mm diff --git a/build/Tests/UnitTests/CoreGraphics/CoreGraphics.UnitTests.vcxproj b/build/Tests/UnitTests/CoreGraphics/CoreGraphics.UnitTests.vcxproj index 12481c1d5e..4138cdc88a 100644 --- a/build/Tests/UnitTests/CoreGraphics/CoreGraphics.UnitTests.vcxproj +++ b/build/Tests/UnitTests/CoreGraphics/CoreGraphics.UnitTests.vcxproj @@ -28,8 +28,8 @@ {0AC27ECF-E2AB-420B-9359-4843FFF4CBFA} - - {26da08da-d0b9-4579-b168-e7f0a5f20e57} + + {6293444C-1461-4CC7-9634-44AB90B8BBC3} {8E79930B-7EF6-4A4E-B46C-EFC0A49C55D9} diff --git a/include/CoreGraphics/CGContext.h b/include/CoreGraphics/CGContext.h index 7029dfe730..c256cbab69 100644 --- a/include/CoreGraphics/CGContext.h +++ b/include/CoreGraphics/CGContext.h @@ -95,7 +95,7 @@ COREGRAPHICS_EXPORT void CGContextSetLineJoin(CGContextRef c, CGLineJoin join); COREGRAPHICS_EXPORT void CGContextSetLineWidth(CGContextRef c, CGFloat width); COREGRAPHICS_EXPORT void CGContextSetMiterLimit(CGContextRef c, CGFloat limit); -COREGRAPHICS_EXPORT void CGContextSetPatternPhase(CGContextRef c, CGSize phase) STUB_METHOD; +COREGRAPHICS_EXPORT void CGContextSetPatternPhase(CGContextRef c, CGSize phase); COREGRAPHICS_EXPORT void CGContextSetFillPattern(CGContextRef c, CGPatternRef pattern, const CGFloat* components); COREGRAPHICS_EXPORT void CGContextSetRenderingIntent(CGContextRef c, CGColorRenderingIntent intent) STUB_METHOD; diff --git a/samples/CGCatalog/CGCatalog/Samples/CGCCGContextSetPatternPhase.m b/samples/CGCatalog/CGCatalog/Samples/CGCCGContextSetPatternPhase.m index c244d6c803..519a015087 100644 --- a/samples/CGCatalog/CGCatalog/Samples/CGCCGContextSetPatternPhase.m +++ b/samples/CGCatalog/CGCatalog/Samples/CGCCGContextSetPatternPhase.m @@ -33,12 +33,6 @@ - (void)drawRect:(CGRect)rect { CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor); CGContextFillRect(context, CGRectMake(0, 0, maxWidth, maxHeight)); - // Create a base pattern color space - CGContextSaveGState(context); - CGColorSpaceRef colorSpace = CGColorSpaceCreatePattern(NULL); - CGContextSetFillColorSpace(context, colorSpace); - CGColorSpaceRelease(colorSpace); - // Create the pattern static const CGPatternCallbacks callbacks = { 0, &_DrawCustomPattern, NULL }; CGFloat alpha = 1; @@ -52,7 +46,6 @@ - (void)drawRect:(CGRect)rect { // Fill using the pattern CGContextFillRect(context, rect); - CGContextRestoreGState(context); } void _DrawCustomPattern(void* info, CGContextRef context) { diff --git a/tests/unittests/CoreGraphics/CGContextTests.mm b/tests/unittests/CoreGraphics/CGContextTests.mm index 55f53899fc..8627ddfa3f 100644 --- a/tests/unittests/CoreGraphics/CGContextTests.mm +++ b/tests/unittests/CoreGraphics/CGContextTests.mm @@ -15,6 +15,107 @@ //****************************************************************************** #import + +#define __CGCONTEXTIMPL_TEST_FRIENDS \ + FRIEND_TEST(CGContext, CGContextSetPatternPhasePatternIsNil); \ + FRIEND_TEST(CGContext, CGContextSetPatternPhaseColorObjectIsFillColor); \ + FRIEND_TEST(CGContext, CGContextSetPatternPhasePositiveChange); \ + FRIEND_TEST(CGContext, CGContextSetPatternPhaseNegativeChange); + #import +#import "CGPatternInternal.h" #import +#import "CGContextInternal.h" +#import "CGContextImpl.h" #import +#import + +void _DrawCustomPattern(void* info, CGContextRef context) { + // Draw a circle inset from the pattern size + CGRect circleRect = CGRectMake(0, 0, 50, 50); + circleRect = CGRectInset(circleRect, 4, 4); + CGContextFillEllipseInRect(context, circleRect); + CGContextStrokeEllipseInRect(context, circleRect); +} + +TEST(CGContext, CGContextSetPatternPhasePatternIsNil) { + // Given + CGContextRef ctx = CGBitmapContextCreate24(1000, 1000); + CGContextImpl* backing = CGContextGetBacking(ctx); + + backing->curState->curFillColorObject = nil; + + // When + CGContextSetPatternPhase(ctx, CGSizeMake(100, 100)); + + // Then + ASSERT_EQ(0, backing->curState->curFillColorObject); + + CGContextRelease(ctx); +} + +TEST(CGContext, CGContextSetPatternPhaseColorObjectIsFillColor) { + // Given + CGContextRef ctx = CGBitmapContextCreate24(1000, 1000); + CGContextImpl* backing = CGContextGetBacking(ctx); + + CGContextSetFillColorWithColor(ctx, [UIColor blueColor].CGColor); + + // When + CGContextSetPatternPhase(ctx, CGSizeMake(100, 100)); + + // Then + ASSERT_EQ(0, (CGColorRef)backing->curState->curFillColorObject); + + CGContextRelease(ctx); +} + +/*TEST(CGContext, CGContextSetPatternPhasePositiveChange) { + // Given + CGContextRef ctx = CGBitmapContextCreate24(1000, 1000); + CGContextImpl* backing = CGContextGetBacking(ctx); + + CGRect boundsRect = CGRectMake(0, 0,1000, 1000); + const CGPatternCallbacks callbacks = { 0, &_DrawCustomPattern, NULL }; + CGFloat alpha = 1; + CGAffineTransform transform = CGAffineTransformMakeTranslation(10, 10); + CGPatternRef pattern = CGPatternCreate( + NULL, boundsRect, transform, 50, 50, kCGPatternTilingConstantSpacing, true, &callbacks); + CGContextSetFillPattern(ctx, pattern, &alpha); + CGPatternRelease(pattern); + + // When + CGContextSetPatternPhase(ctx, CGSizeMake(100, 200)); + + // Then + CGPattern* actualPattern = (CGPattern*)backing->curState->curFillColorObject; + ASSERT_EQ(110, actualPattern->matrix.tx); + ASSERT_EQ(210, actualPattern->matrix.ty); + + CGContextRelease(ctx); +} + +TEST(CGContext, CGContextSetPatternPhaseNegativeChange) { + // Given + CGContextRef ctx = CGBitmapContextCreate24(1000, 1000); + CGContextImpl* backing = CGContextGetBacking(ctx); + + CGRect boundsRect = CGRectMake(0, 0,1000, 1000); + const CGPatternCallbacks callbacks = { 0, &_DrawCustomPattern, NULL }; + CGFloat alpha = 1; + CGAffineTransform transform = CGAffineTransformMakeTranslation(300, 500); + CGPatternRef pattern = CGPatternCreate( + NULL, boundsRect, transform, 50, 50, kCGPatternTilingConstantSpacing, true, &callbacks); + CGContextSetFillPattern(ctx, pattern, &alpha); + CGPatternRelease(pattern); + + // When + CGContextSetPatternPhase(ctx, CGSizeMake(-100, -200)); + + // Then + CGPattern* actualPattern = (CGPattern*)backing->curState->curFillColorObject; + ASSERT_EQ(200, actualPattern->matrix.tx); + ASSERT_EQ(300, actualPattern->matrix.ty); + + CGContextRelease(ctx); +}*/