Skip to content

Commit

Permalink
Implemented CGContextSetPatternPhase (#596)
Browse files Browse the repository at this point in the history
Implemented CGContextSetPatternPhase using the translation portion of the
pattern's transform matrix. Also contains a fix for a missing retain in
CGContextSetFillPattern.

Implements last item in Issue #524
  • Loading branch information
adein authored and jaredhms committed Jul 1, 2016
1 parent 3c0f560 commit 788d389
Show file tree
Hide file tree
Showing 8 changed files with 125 additions and 18 deletions.
5 changes: 2 additions & 3 deletions Frameworks/CoreGraphics/CGContext.mm
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/**
Expand Down
12 changes: 11 additions & 1 deletion Frameworks/CoreGraphics/CGContextImpl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@

void CGContextImpl::CGContextSetFillPattern(CGPatternRef pattern, const float* components) {
CGPattern* intPattern = (CGPattern*)pattern;
curState->curFillColorObject = pattern;
curState->curFillColorObject = [pattern retain];
switch (intPattern->surfaceFmt) {
case _ColorRGB:
case _Color565:
Expand All @@ -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;
Expand Down
7 changes: 7 additions & 0 deletions Frameworks/include/CGContextImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
//******************************************************************************

#pragma once

#ifndef __CGCONTEXTIMPL_TEST_FRIENDS
#define __CGCONTEXTIMPL_TEST_FRIENDS
#endif

#include "CGContextInternal.h"

#include "CoreGraphics/CGPath.h"
Expand Down Expand Up @@ -53,6 +58,7 @@ typedef struct {
#define MAX_CG_STATES 16

class CGContextImpl {
__CGCONTEXTIMPL_TEST_FRIENDS;
protected:
CGContextRef _rootContext;
CGImageRef _imgDest;
Expand Down Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions build/CoreGraphics/dll/CoreGraphics.def
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ LIBRARY CoreGraphics
CGContextIsDirty
CGContextReleaseLock
CGContextSetDirty
CGContextGetBacking
EbrCenterTextInRectVertically

; CGDataConsumer.mm
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,9 @@
<ProjectReference Include="..\..\..\CoreGraphics\dll\CoreGraphics.vcxproj">
<Project>{26da08da-d0b9-4579-b168-e7f0a5f20e57}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\UIKit\dll\UIKit.vcxproj">
<Project>{8E79930B-7EF6-4A4E-B46C-EFC0A49C55D9}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\AutoLayout\dll\AutoLayout.vcxproj">
<Project>{D036FDB1-F82C-40C7-B1B4-65F499EAE116}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\QuartzCore\dll\QuartzCore.vcxproj">
<Project>{037B568F-4104-417E-9FB8-B6899E398903}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\WinObjCRT\dll\WinObjCRT.vcxproj">
<Project>{585b4870-0d6b-43a6-8e7e-ad08f7f507b6}</Project>
</ProjectReference>
Expand Down
2 changes: 1 addition & 1 deletion include/CoreGraphics/CGContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -52,7 +46,6 @@ - (void)drawRect:(CGRect)rect {

// Fill using the pattern
CGContextFillRect(context, rect);
CGContextRestoreGState(context);
}

void _DrawCustomPattern(void* info, CGContextRef context) {
Expand Down
103 changes: 103 additions & 0 deletions tests/unittests/CoreGraphics/CGContextTests.mm
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,109 @@
//******************************************************************************

#import <TestFramework.h>

#define __CGCONTEXTIMPL_TEST_FRIENDS \
FRIEND_TEST(CGContext, CGContextSetPatternPhasePatternIsNil); \
FRIEND_TEST(CGContext, CGContextSetPatternPhaseColorObjectIsFillColor); \
FRIEND_TEST(CGContext, CGContextSetPatternPhasePositiveChange); \
FRIEND_TEST(CGContext, CGContextSetPatternPhaseNegativeChange);

#import <Starboard.h>
#import "CGPatternInternal.h"
#import <CoreGraphics\CGContext.h>
#import "CGContextInternal.h"
#import "CGContextImpl.h"
#import <Foundation\Foundation.h>
#import <CoreGraphics\CGPattern.h>

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;
CGAffineTransform matrix = [actualPattern getPatternTransform];
ASSERT_EQ(110, matrix.tx);
ASSERT_EQ(210, 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;
CGAffineTransform matrix = [actualPattern getPatternTransform];
ASSERT_EQ(200, matrix.tx);
ASSERT_EQ(300, matrix.ty);

CGContextRelease(ctx);
}

0 comments on commit 788d389

Please sign in to comment.