[dali_2.3.21] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-physics / third-party / chipmunk2d / objectivec / src / ChipmunkImageSampler.m
1 // Copyright 2013 Howling Moon Software. All rights reserved.
2 // See http://chipmunk2d.net/legal.php for more information.
3
4 //
5 //  ChipmunkImageSampler.m
6 //  DeformableChipmunk
7 //
8 //  Created by Scott Lembcke on 8/26/11.
9 //  Copyright 2011 __MyCompanyName__. All rights reserved.
10 //
11
12 #import <TargetConditionals.h>
13
14 #if TARGET_OS_IPHONE == 1
15         #import <ImageIO/ImageIO.h>
16 #endif
17
18 #import "ChipmunkImageSampler.h"
19
20 @implementation ChipmunkBitmapSampler
21
22 @synthesize width = _width, height = _height, bytesPerPixel = _bytesPerPixel, component = _component, pixelData = _pixelData, outputRect = _outputRect;
23
24 // Much faster than (int)floor(f)
25 // Profiling showed floor() to be a sizable performance hog
26 static inline int
27 floor_int(cpFloat f)
28 {
29         int i = (int)f;
30         return (f < 0.0f && f != i ? i - 1 : i);
31 }
32
33 // TODO finish this?
34 //static inline cpFloat
35 //SampleFunc4444(cpVect point, ChipmunkImageSampler *self)
36 //{
37 //      int x = (int)point.x;
38 //      int y = (int)point.y - (self->_flip ? self->_height - 1 : 0);
39 //      
40 //      int com = self->_component;
41 //      int byte = self->_pixels[y*self->_stride + x*self->_bytesPerPixel + com/2];
42 //      int value = 
43 //      return (cpFloat)(byte>>())/15.0;
44 //}
45
46 static cpFloat
47 SampleFunc8Clamp(cpVect point, ChipmunkBitmapSampler *self)
48 {
49         unsigned long w = self->_width;
50         unsigned long h = self->_height;
51         
52         cpBB bb = self->_outputRect;
53         cpVect clamped = cpBBClampVect(bb, point);
54         
55         unsigned long x = floor_int((w - 1)*(clamped.x - bb.l)/(bb.r - bb.l) + 0.5);
56         unsigned long y = floor_int((h - 1)*(clamped.y - bb.b)/(bb.t - bb.b) + 0.5);
57         
58         if(self->_flip) y = h - 1 - y;
59         
60 //      printf("(%6.2f, %6.2f) -> (% 4d, % 4d) : %d\n", point.x, point.y, x, y, self->_pixels[y*self->_stride + x*self->_bytesPerPixel + self->_component]);
61         return (cpFloat)self->_pixels[y*self->_stride + x*self->_bytesPerPixel + self->_component]/255.0;
62 }
63
64 static cpFloat
65 SampleFunc8Border(cpVect point, ChipmunkBitmapSampler *self)
66 {
67         unsigned long w = self->_width;
68         unsigned long h = self->_height;
69         
70         cpBB bb = self->_outputRect;
71         if(cpBBContainsVect(bb, point)){
72                 unsigned long x = floor_int((w - 1)*(point.x - bb.l)/(bb.r - bb.l) + 0.5);
73                 unsigned long y = floor_int((h - 1)*(point.y - bb.b)/(bb.t - bb.b) + 0.5);
74                 
75                 if(self->_flip) y = h - 1 - y;
76                 
77 //              printf("(%6.2f, %6.2f) -> (% 4d, % 4d)\n", point.x, point.y, x, y);
78                 return (cpFloat)self->_pixels[y*self->_stride + x*self->_bytesPerPixel + self->_component]/255.0;
79         } else {
80                 return self->_borderValue;
81         }
82 }
83
84 -(id)initWithWidth:(NSUInteger)width height:(NSUInteger)height stride:(NSUInteger)stride bytesPerPixel:(NSUInteger)bytesPerPixel component:(NSUInteger)component flip:(bool)flip pixelData:(NSData *)pixelData
85 {
86         if((self = [super initWithSamplingFunction:(cpMarchSampleFunc)SampleFunc8Clamp])){
87                 _width = width;
88                 _height = height;
89                 _stride = stride;
90                 
91                 _bytesPerPixel = bytesPerPixel;
92                 _component = component;
93                 
94                 _flip = flip;
95                 _pixelData = [pixelData retain];
96                 _pixels = [pixelData bytes];
97                 
98                 _outputRect = cpBBNew(0.5, 0.5, self.width - 0.5, self.height - 0.5);
99         }
100
101         return self;
102 }
103
104
105 - (void)dealloc
106 {
107         [_pixelData release];
108         
109         [super dealloc];
110 }
111
112 -(void)setBorderRepeat
113 {
114         _sampleFunc = (cpMarchSampleFunc)SampleFunc8Clamp;
115 }
116
117 -(void)setBorderValue:(cpFloat)borderValue
118 {
119         _sampleFunc = (cpMarchSampleFunc)SampleFunc8Border;
120         _borderValue = borderValue;
121 }
122
123 static cpBB
124 BorderedBB(cpBB bb, NSUInteger width, NSUInteger height)
125 {
126         cpFloat xBorder = (bb.r - bb.l)/(cpFloat)(width - 1);
127         cpFloat yBorder = (bb.t - bb.b)/(cpFloat)(height - 1);
128         
129         return cpBBNew(bb.l - xBorder, bb.b - yBorder, bb.r + xBorder, bb.t + yBorder);
130 }
131
132 -(ChipmunkPolylineSet *)marchAllWithBorder:(bool)bordered hard:(bool)hard
133 {
134         NSUInteger width = self.width;
135         NSUInteger height = self.height;
136         cpBB bb = self.outputRect;
137         
138         if(bordered){
139                 return [self march:BorderedBB(bb, width, height) xSamples:width+2 ySamples:height+2 hard:hard];
140         } else {
141                 return [self march:bb xSamples:width ySamples:height hard:hard];
142         }
143 }
144
145 @end
146
147
148
149 @implementation ChipmunkCGContextSampler
150
151 @synthesize context = _context;
152
153 -(NSMutableData *)pixelData {return (NSMutableData *)super.pixelData;}
154
155 -(id)initWithWidth:(unsigned long)width height:(unsigned long)height colorSpace:(CGColorSpaceRef)colorSpace bitmapInfo:(CGBitmapInfo)bitmapInfo component:(NSUInteger)component
156 {
157         // Need to create a context to get info about the context.
158         // If you let the context allocate it's own memory it seems to move it around. O_o
159         CGContextRef temp = CGBitmapContextCreate(NULL, width, height, 8, 0, colorSpace, bitmapInfo);
160         cpAssertHard(temp, "Failed to create temporary CGBitmapContext");
161         
162         unsigned long bpc = CGBitmapContextGetBitsPerComponent(temp);
163         unsigned long bpp = CGBitmapContextGetBitsPerPixel(temp)/8;
164         cpAssertHard(bpc == 8, "Cannot handle non-8bit-per-pixel bitmap data!");
165         
166         CGContextRelease(temp); 
167         
168         unsigned long stride = width*bpp;
169         NSMutableData *pixelData = [NSMutableData dataWithLength:stride*height];
170         _context = CGBitmapContextCreate([pixelData mutableBytes], width, height, bpc, stride, colorSpace, bitmapInfo);
171         
172         return [self initWithWidth:width height:height stride:stride bytesPerPixel:bpp component:component flip:TRUE pixelData:pixelData];
173 }
174
175 -(void)dealloc
176 {
177         CGContextRelease(_context);
178         
179         [super dealloc];
180 }
181
182 @end
183
184
185
186 @implementation ChipmunkImageSampler
187
188 +(CGImageRef)loadImage:(NSURL *)url
189 {
190         CGImageSourceRef image_source = CGImageSourceCreateWithURL((CFURLRef)url, NULL);
191         CGImageRef image = CGImageSourceCreateImageAtIndex(image_source, 0, NULL);
192         cpAssertHard(image, "Image %s could not be loaded.", [[url description] UTF8String]);
193         
194         CFRelease(image_source);
195         return image;
196 }
197
198 -(id)initWithImage:(CGImageRef)image isMask:(bool)isMask contextWidth:(NSUInteger)width contextHeight:(NSUInteger)height
199 {
200         if(width == 0) width = CGImageGetWidth(image);
201         if(height == 0)  height = CGImageGetHeight(image);
202         
203         CGColorSpaceRef colorSpace = (isMask ? CGColorSpaceCreateDeviceGray() : NULL);
204         CGBitmapInfo bitmapInfo = (CGBitmapInfo)(isMask ? kCGImageAlphaNone : kCGImageAlphaOnly);
205         
206         if((self = [super initWithWidth:width height:height colorSpace:colorSpace bitmapInfo:bitmapInfo component:0])){
207                 CGContextDrawImage(self.context, CGRectMake(0, 0, width, height), image);
208         }
209         
210         CGColorSpaceRelease(colorSpace);
211         
212         return self;
213 }
214
215 -(id)initWithImageFile:(NSURL *)url isMask:(bool)isMask
216 {
217         CGImageRef image = [[self class] loadImage:url];
218         unsigned long width = CGImageGetWidth(image);
219         unsigned long height = CGImageGetHeight(image);
220         
221         self = [self initWithImage:image isMask:isMask contextWidth:width contextHeight:height];
222         
223         CGImageRelease(image);
224         
225         return self;
226 }
227
228 +(ChipmunkImageSampler *)samplerWithImageFile:(NSURL *)url isMask:(bool)isMask
229 {
230         return [[[self alloc] initWithImageFile:url     isMask:isMask] autorelease];
231 }
232
233 @end