Permalink
Browse files

Added support for createPattern; only works with POT textures

  • Loading branch information...
1 parent c6386db commit fc99e90204b6aac54d637d82b36fcec74c4f77e2 @phoboslab committed Jan 6, 2013
@@ -52,6 +52,8 @@
B64CE697166682B10087CF94 /* Icon.png in Resources */ = {isa = PBXBuildFile; fileRef = B64CE68C166682B10087CF94 /* Icon.png */; };
B64CE698166682B10087CF94 /* Icon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B64CE68D166682B10087CF94 /* Icon@2x.png */; };
B64CE699166682B10087CF94 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = B64CE68E166682B10087CF94 /* MainWindow.xib */; };
+ B664B98B1699F3380093E04E /* EJBindingCanvasPattern.m in Sources */ = {isa = PBXBuildFile; fileRef = B664B98A1699F3380093E04E /* EJBindingCanvasPattern.m */; };
+ B664B98E1699F49C0093E04E /* EJCanvasPattern.m in Sources */ = {isa = PBXBuildFile; fileRef = B664B98D1699F49B0093E04E /* EJCanvasPattern.m */; };
B66F1E801476B6A40090D208 /* libstdc++.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B66F1E7F1476B6A40090D208 /* libstdc++.dylib */; };
B66F1E811476B6B90090D208 /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = B66F1E771476B3AC0090D208 /* libicucore.dylib */; };
B68037011682A58300833604 /* EJConvertWebGL.m in Sources */ = {isa = PBXBuildFile; fileRef = B68037001682A58200833604 /* EJConvertWebGL.m */; };
@@ -159,6 +161,10 @@
B64CE68C166682B10087CF94 /* Icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Icon.png; sourceTree = "<group>"; };
B64CE68D166682B10087CF94 /* Icon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon@2x.png"; sourceTree = "<group>"; };
B64CE68E166682B10087CF94 /* MainWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = "<group>"; };
+ B664B9891699F3370093E04E /* EJBindingCanvasPattern.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EJBindingCanvasPattern.h; sourceTree = "<group>"; };
+ B664B98A1699F3380093E04E /* EJBindingCanvasPattern.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EJBindingCanvasPattern.m; sourceTree = "<group>"; };
+ B664B98C1699F49B0093E04E /* EJCanvasPattern.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EJCanvasPattern.h; sourceTree = "<group>"; };
+ B664B98D1699F49B0093E04E /* EJCanvasPattern.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EJCanvasPattern.m; sourceTree = "<group>"; };
B66F1E771476B3AC0090D208 /* libicucore.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libicucore.dylib; path = usr/lib/libicucore.dylib; sourceTree = SDKROOT; };
B66F1E7F1476B6A40090D208 /* libstdc++.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libstdc++.dylib"; path = "usr/lib/libstdc++.dylib"; sourceTree = SDKROOT; };
B68036FF1682A58200833604 /* EJConvertWebGL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = EJConvertWebGL.h; path = WebGL/EJConvertWebGL.h; sourceTree = "<group>"; };
@@ -433,6 +439,10 @@
B6F114F11676BD40001F1324 /* EJCanvasContext2DScreen.m */,
B6F114F21676BD40001F1324 /* EJCanvasContext2DTexture.h */,
B6F114F31676BD40001F1324 /* EJCanvasContext2DTexture.m */,
+ B664B9891699F3370093E04E /* EJBindingCanvasPattern.h */,
+ B664B98A1699F3380093E04E /* EJBindingCanvasPattern.m */,
+ B664B98C1699F49B0093E04E /* EJCanvasPattern.h */,
+ B664B98D1699F49B0093E04E /* EJCanvasPattern.m */,
B6F114EC1676BD40001F1324 /* EJBindingImageData.h */,
B6F114ED1676BD40001F1324 /* EJBindingImageData.m */,
B6F114F61676BD40001F1324 /* EJImageData.h */,
@@ -582,6 +592,8 @@
B6F11556167BD59D001F1324 /* EJBindingWebGLObjects.m in Sources */,
B6F115B7167E895B001F1324 /* EJGLProgram2D.m in Sources */,
B68037011682A58300833604 /* EJConvertWebGL.m in Sources */,
+ B664B98B1699F3380093E04E /* EJBindingCanvasPattern.m in Sources */,
+ B664B98E1699F49C0093E04E /* EJCanvasPattern.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -3,6 +3,7 @@
#import "EJCanvasContext2DTexture.h"
#import "EJCanvasContext2DScreen.h"
#import "EJBindingImageData.h"
+#import "EJBindingCanvasPattern.h"
#import "EJDrawable.h"
#import "EJConvertColorRGBA.h"
@@ -68,11 +69,22 @@ - (void)dealloc {
);
EJ_BIND_GET(fillStyle, ctx ) {
- return ColorRGBAToJSValue(ctx, renderingContext.state->fillColor);
+ if( renderingContext.fillPattern ) {
+ return [EJBindingCanvasPattern createJSObjectWithContext:ctx pattern:renderingContext.fillPattern];
+ }
+ else {
+ return ColorRGBAToJSValue(ctx, renderingContext.state->fillColor);
+ }
}
EJ_BIND_SET(fillStyle, ctx, value) {
- renderingContext.state->fillColor = JSValueToColorRGBA(ctx, value);
+ if( JSValueIsObject(ctx, value) ) {
+ renderingContext.fillPattern = [EJBindingCanvasPattern patternFromJSValue:value];
+ }
+ else {
+ renderingContext.state->fillColor = JSValueToColorRGBA(ctx, value);
+ renderingContext.fillPattern = NULL;
+ }
}
EJ_BIND_GET(strokeStyle, ctx ) {
@@ -278,6 +290,30 @@ - (void)dealloc {
return NULL;
}
+EJ_BIND_FUNCTION(createPattern, ctx, argc, argv) {
+ if( argc < 1 ) { return NULL; }
+ NSObject<EJDrawable> * drawable = (NSObject<EJDrawable> *)JSObjectGetPrivate((JSObjectRef)argv[0]);
+ EJTexture * image = drawable.texture;
+
+ if( !image ) { return NULL; }
+
+ EJCanvasPatternRepeat repeat = kEJCanvasPatternRepeat;
+ if( argc > 1 ) {
+ NSString * repeatString = JSValueToNSString(ctx, argv[1]);
+ if( [repeatString isEqualToString:@"repeat-x"] ) {
+ repeat = kEJCanvasPatternRepeatX;
+ }
+ else if( [repeatString isEqualToString:@"repeat-y"] ) {
+ repeat = kEJCanvasPatternRepeatY;
+ }
+ else if( [repeatString isEqualToString:@"no-repeat"] ) {
+ repeat = kEJCanvasPatternNoRepeat;
+ }
+ }
+ EJCanvasPattern * pattern = [[[EJCanvasPattern alloc] initWithTexture:image repeat:repeat] autorelease];
+ return [EJBindingCanvasPattern createJSObjectWithContext:ctx pattern:pattern];
+}
+
EJ_BIND_FUNCTION( beginPath, ctx, argc, argv ) {
[renderingContext beginPath];
return NULL;
@@ -393,7 +429,6 @@ - (void)dealloc {
EJ_BIND_FUNCTION_NOT_IMPLEMENTED( createRadialGradient );
EJ_BIND_FUNCTION_NOT_IMPLEMENTED( createLinearGradient );
-EJ_BIND_FUNCTION_NOT_IMPLEMENTED( createPattern );
EJ_BIND_FUNCTION_NOT_IMPLEMENTED( isPointInPath );
@end
@@ -0,0 +1,11 @@
+#import "EJBindingBase.h"
+#import "EJCanvasPattern.h"
+
+@interface EJBindingCanvasPattern : EJBindingBase {
+ EJCanvasPattern * pattern;
+}
+
++ (JSObjectRef)createJSObjectWithContext:(JSContextRef)ctx pattern:(EJCanvasPattern *)pattern;
++ (EJCanvasPattern *)patternFromJSValue:(JSValueRef)value;
+
+@end
@@ -0,0 +1,24 @@
+#import "EJBindingCanvasPattern.h"
+
+@implementation EJBindingCanvasPattern
+
++ (JSObjectRef)createJSObjectWithContext:(JSContextRef)ctx pattern:(EJCanvasPattern *)pattern {
+ EJBindingCanvasPattern * binding = [[EJBindingCanvasPattern alloc] initWithContext:ctx argc:0 argv:NULL];
+ binding->pattern = [pattern retain];
+
+ return [self createJSObjectWithContext:ctx instance:binding];
+}
+
++ (EJCanvasPattern *)patternFromJSValue:(JSValueRef)value {
+ if( !value ) { return NULL; }
+
+ EJBindingCanvasPattern * binding = (EJBindingCanvasPattern *)JSObjectGetPrivate((JSObjectRef)value);
+ return (binding && [binding isMemberOfClass:[EJBindingCanvasPattern class]]) ? binding->pattern : NULL;
+}
+
+- (void)dealloc {
+ [pattern release];
+ [super dealloc];
+}
+
+@end
@@ -1,6 +1,7 @@
#import <Foundation/Foundation.h>
#import "EJTexture.h"
#import "EJImageData.h"
+#import "EJCanvasPattern.h"
#import "EJPath.h"
#import "EJCanvas2DTypes.h"
#import "EJCanvasContext.h"
@@ -56,6 +57,7 @@ typedef struct {
EJCompositeOperation globalCompositeOperation;
EJColorRGBA fillColor;
+ EJCanvasPattern * fillPattern;
EJColorRGBA strokeColor;
float globalAlpha;
@@ -154,6 +156,7 @@ typedef struct {
@property (nonatomic) EJCanvasState * state;
@property (nonatomic) EJCompositeOperation globalCompositeOperation;
@property (nonatomic, retain) UIFont * font;
+@property (nonatomic, retain) EJCanvasPattern * fillPattern;
@property (nonatomic, assign) float backingStoreRatio;
@property (nonatomic) BOOL imageSmoothingEnabled;
@@ -336,6 +336,15 @@ - (UIFont *)font {
return state->font;
}
+- (void)setFillPattern:(EJCanvasPattern *)fillPattern {
+ [state->fillPattern release];
+ state->fillPattern = [fillPattern retain];
+}
+
+- (EJCanvasPattern *)fillPattern {
+ return state->fillPattern;
+}
+
- (void)save {
if( stateIndex == EJ_CANVAS_STATE_STACK_SIZE-1 ) {
@@ -347,6 +356,7 @@ - (void)save {
stateIndex++;
state = &stateStack[stateIndex];
[state->font retain];
+ [state->fillPattern retain];
[state->clipPath retain];
}
@@ -358,6 +368,7 @@ - (void)restore {
// Clean up current state
[state->font release];
+ [state->fillPattern release];
if( state->clipPath && state->clipPath != stateStack[stateIndex-1].clipPath ) {
[self resetClip];
@@ -418,11 +429,24 @@ - (void)drawImage:(EJTexture *)texture sx:(float)sx sy:(float)sy sw:(float)sw sh
}
- (void)fillRectX:(float)x y:(float)y w:(float)w h:(float)h {
- [self setTexture:NULL];
-
- EJColorRGBA color = state->fillColor;
- color.rgba.a = (float)color.rgba.a * state->globalAlpha;
- [self pushRectX:x y:y w:w h:h color:color withTransform:state->transform];
+ if( state->fillPattern ) {
+ [self setTexture:state->fillPattern.texture];
+ EJColorRGBA color = {.rgba = {255, 255, 255, 255 * state->globalAlpha}};
+
+ float
+ tx = 0,
+ ty = 0,
+ tw = w / currentTexture.width,
+ th = h / currentTexture.height;
+ [self pushTexturedRectX:x y:y w:w h:h tx:tx ty:ty tw:tw th:th color:color withTransform:state->transform];
+ }
+ else {
+ [self setTexture:NULL];
+
+ EJColorRGBA color = state->fillColor;
+ color.rgba.a = (float)color.rgba.a * state->globalAlpha;
+ [self pushRectX:x y:y w:w h:h color:color withTransform:state->transform];
+ }
}
- (void)strokeRectX:(float)x y:(float)y w:(float)w h:(float)h {
@@ -0,0 +1,21 @@
+#import <Foundation/Foundation.h>
+#import "EJTexture.h"
+
+typedef enum {
+ kEJCanvasPatternNoRepeat = 0,
+ kEJCanvasPatternRepeatX = 1,
+ kEJCanvasPatternRepeatY = 2,
+ kEJCanvasPatternRepeat = 1 | 2,
+} EJCanvasPatternRepeat;
+
+@interface EJCanvasPattern : NSObject {
+ EJTexture * texture;
+ EJCanvasPatternRepeat repeat;
+}
+
+- (id)initWithTexture:(EJTexture *)texturep repeat:(EJCanvasPatternRepeat)repeatp;
+
+@property (readonly, nonatomic) EJTexture * texture;
+@property (readonly, nonatomic) EJCanvasPatternRepeat repeat;
+
+@end
@@ -0,0 +1,24 @@
+#import "EJCanvasPattern.h"
+
+@implementation EJCanvasPattern
+
+@synthesize texture;
+@synthesize repeat;
+
+- (id)initWithTexture:(EJTexture *)texturep repeat:(EJCanvasPatternRepeat)repeatp {
+ if( self = [super init] ) {
+ texture = texturep.copy;
+ repeat = repeatp;
+
+ [texture setParam:GL_TEXTURE_WRAP_S param: (repeat & kEJCanvasPatternRepeatX) ? GL_REPEAT : GL_CLAMP_TO_EDGE];
+ [texture setParam:GL_TEXTURE_WRAP_T param: (repeat & kEJCanvasPatternRepeatY) ? GL_REPEAT : GL_CLAMP_TO_EDGE];
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [texture release];
+ [super dealloc];
+}
+
+@end
@@ -37,16 +37,20 @@ - (void)bindToTarget:(GLenum)target withParams:(EJTextureParam *)newParams {
// Check if we have to set a param
if(params[kEJTextureParamMinFilter] != newParams[kEJTextureParamMinFilter]) {
- glTexParameteri(target, GL_TEXTURE_MIN_FILTER, newParams[kEJTextureParamMinFilter]);
+ params[kEJTextureParamMinFilter] = newParams[kEJTextureParamMinFilter];
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER, params[kEJTextureParamMinFilter]);
}
if(params[kEJTextureParamMagFilter] != newParams[kEJTextureParamMagFilter]) {
- glTexParameteri(target, GL_TEXTURE_MAG_FILTER, newParams[kEJTextureParamMagFilter]);
+ params[kEJTextureParamMagFilter] = newParams[kEJTextureParamMagFilter];
+ glTexParameteri(target, GL_TEXTURE_MAG_FILTER, params[kEJTextureParamMagFilter]);
}
if(params[kEJTextureParamWrapS] != newParams[kEJTextureParamWrapS]) {
- glTexParameteri(target, GL_TEXTURE_WRAP_S, newParams[kEJTextureParamWrapS]);
+ params[kEJTextureParamWrapS] = newParams[kEJTextureParamWrapS];
+ glTexParameteri(target, GL_TEXTURE_WRAP_S, params[kEJTextureParamWrapS]);
}
if(params[kEJTextureParamWrapT] != newParams[kEJTextureParamWrapT]) {
- glTexParameteri(target, GL_TEXTURE_WRAP_T, newParams[kEJTextureParamWrapT]);
+ params[kEJTextureParamWrapT] = newParams[kEJTextureParamWrapT];
+ glTexParameteri(target, GL_TEXTURE_WRAP_T, params[kEJTextureParamWrapT]);
}
}
@@ -213,6 +217,19 @@ - (BOOL)isDynamic {
return !fullPath;
}
+- (id)copyWithZone:(NSZone *)zone {
+ EJTexture * copy = [[EJTexture allocWithZone:zone] init];
+ memcpy(copy->params, params, sizeof(EJTextureParams));
+ copy->owningContext = owningContext;
+ [copy createWithTexture:self];
+
+ if( self.isDynamic ) {
+ //[copy createWithPixels:self.pixels format:format];
+ }
+
+ return copy;
+}
+
- (void)createWithTexture:(EJTexture *)other {
[textureStorage release];
[fullPath release];

0 comments on commit fc99e90

Please sign in to comment.