diff options
Diffstat (limited to 'libs/cocos2d/CCTexture2D.m')
-rwxr-xr-x | libs/cocos2d/CCTexture2D.m | 814 |
1 files changed, 814 insertions, 0 deletions
diff --git a/libs/cocos2d/CCTexture2D.m b/libs/cocos2d/CCTexture2D.m new file mode 100755 index 0000000..afa64e2 --- /dev/null +++ b/libs/cocos2d/CCTexture2D.m | |||
@@ -0,0 +1,814 @@ | |||
1 | /* | ||
2 | |||
3 | ===== IMPORTANT ===== | ||
4 | |||
5 | This is sample code demonstrating API, technology or techniques in development. | ||
6 | Although this sample code has been reviewed for technical accuracy, it is not | ||
7 | final. Apple is supplying this information to help you plan for the adoption of | ||
8 | the technologies and programming interfaces described herein. This information | ||
9 | is subject to change, and software implemented based on this sample code should | ||
10 | be tested with final operating system software and final documentation. Newer | ||
11 | versions of this sample code may be provided with future seeds of the API or | ||
12 | technology. For information about updates to this and other developer | ||
13 | documentation, view the New & Updated sidebars in subsequent documentationd | ||
14 | seeds. | ||
15 | |||
16 | ===================== | ||
17 | |||
18 | File: Texture2D.m | ||
19 | Abstract: Creates OpenGL 2D textures from images or text. | ||
20 | |||
21 | Version: 1.6 | ||
22 | |||
23 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. | ||
24 | ("Apple") in consideration of your agreement to the following terms, and your | ||
25 | use, installation, modification or redistribution of this Apple software | ||
26 | constitutes acceptance of these terms. If you do not agree with these terms, | ||
27 | please do not use, install, modify or redistribute this Apple software. | ||
28 | |||
29 | In consideration of your agreement to abide by the following terms, and subject | ||
30 | to these terms, Apple grants you a personal, non-exclusive license, under | ||
31 | Apple's copyrights in this original Apple software (the "Apple Software"), to | ||
32 | use, reproduce, modify and redistribute the Apple Software, with or without | ||
33 | modifications, in source and/or binary forms; provided that if you redistribute | ||
34 | the Apple Software in its entirety and without modifications, you must retain | ||
35 | this notice and the following text and disclaimers in all such redistributions | ||
36 | of the Apple Software. | ||
37 | Neither the name, trademarks, service marks or logos of Apple Inc. may be used | ||
38 | to endorse or promote products derived from the Apple Software without specific | ||
39 | prior written permission from Apple. Except as expressly stated in this notice, | ||
40 | no other rights or licenses, express or implied, are granted by Apple herein, | ||
41 | including but not limited to any patent rights that may be infringed by your | ||
42 | derivative works or by other works in which the Apple Software may be | ||
43 | incorporated. | ||
44 | |||
45 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO | ||
46 | WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED | ||
47 | WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||
48 | PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN | ||
49 | COMBINATION WITH YOUR PRODUCTS. | ||
50 | |||
51 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR | ||
52 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE | ||
53 | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
54 | ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR | ||
55 | DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF | ||
56 | CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF | ||
57 | APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
58 | |||
59 | Copyright (C) 2008 Apple Inc. All Rights Reserved. | ||
60 | |||
61 | */ | ||
62 | |||
63 | /* | ||
64 | * Support for RGBA_4_4_4_4 and RGBA_5_5_5_1 was copied from: | ||
65 | * https://devforums.apple.com/message/37855#37855 by a1studmuffin | ||
66 | */ | ||
67 | |||
68 | |||
69 | #import <Availability.h> | ||
70 | |||
71 | #import "Platforms/CCGL.h" | ||
72 | #import "Platforms/CCNS.h" | ||
73 | |||
74 | |||
75 | #import "CCTexture2D.h" | ||
76 | #import "ccConfig.h" | ||
77 | #import "ccMacros.h" | ||
78 | #import "CCConfiguration.h" | ||
79 | #import "Support/ccUtils.h" | ||
80 | #import "CCTexturePVR.h" | ||
81 | |||
82 | #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && CC_FONT_LABEL_SUPPORT | ||
83 | // FontLabel support | ||
84 | #import "FontManager.h" | ||
85 | #import "FontLabelStringDrawing.h" | ||
86 | #endif// CC_FONT_LABEL_SUPPORT | ||
87 | |||
88 | |||
89 | // For Labels use 16-bit textures on iPhone 3GS / iPads since A8 textures are very slow | ||
90 | #if (defined(__ARM_NEON__) || TARGET_IPHONE_SIMULATOR) && CC_USE_LA88_LABELS_ON_NEON_ARCH | ||
91 | #define USE_TEXT_WITH_A8_TEXTURES 0 | ||
92 | |||
93 | #else | ||
94 | #define USE_TEXT_WITH_A8_TEXTURES 1 | ||
95 | #endif | ||
96 | |||
97 | //CLASS IMPLEMENTATIONS: | ||
98 | |||
99 | |||
100 | // If the image has alpha, you can create RGBA8 (32-bit) or RGBA4 (16-bit) or RGB5A1 (16-bit) | ||
101 | // Default is: RGBA8888 (32-bit textures) | ||
102 | static CCTexture2DPixelFormat defaultAlphaPixelFormat_ = kCCTexture2DPixelFormat_Default; | ||
103 | |||
104 | #pragma mark - | ||
105 | #pragma mark CCTexture2D - Main | ||
106 | |||
107 | @implementation CCTexture2D | ||
108 | |||
109 | @synthesize contentSizeInPixels = size_, pixelFormat = format_, pixelsWide = width_, pixelsHigh = height_, name = name_, maxS = maxS_, maxT = maxT_; | ||
110 | @synthesize hasPremultipliedAlpha = hasPremultipliedAlpha_; | ||
111 | |||
112 | - (id) initWithData:(const void*)data pixelFormat:(CCTexture2DPixelFormat)pixelFormat pixelsWide:(NSUInteger)width pixelsHigh:(NSUInteger)height contentSize:(CGSize)size | ||
113 | { | ||
114 | if((self = [super init])) { | ||
115 | glPixelStorei(GL_UNPACK_ALIGNMENT,1); | ||
116 | glGenTextures(1, &name_); | ||
117 | glBindTexture(GL_TEXTURE_2D, name_); | ||
118 | |||
119 | [self setAntiAliasTexParameters]; | ||
120 | |||
121 | // Specify OpenGL texture image | ||
122 | |||
123 | switch(pixelFormat) | ||
124 | { | ||
125 | case kCCTexture2DPixelFormat_RGBA8888: | ||
126 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei) width, (GLsizei) height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); | ||
127 | break; | ||
128 | case kCCTexture2DPixelFormat_RGBA4444: | ||
129 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei) width, (GLsizei) height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, data); | ||
130 | break; | ||
131 | case kCCTexture2DPixelFormat_RGB5A1: | ||
132 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei) width, (GLsizei) height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, data); | ||
133 | break; | ||
134 | case kCCTexture2DPixelFormat_RGB565: | ||
135 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, (GLsizei) width, (GLsizei) height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data); | ||
136 | break; | ||
137 | case kCCTexture2DPixelFormat_AI88: | ||
138 | glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, (GLsizei) width, (GLsizei) height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, data); | ||
139 | break; | ||
140 | case kCCTexture2DPixelFormat_A8: | ||
141 | glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, (GLsizei) width, (GLsizei) height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, data); | ||
142 | break; | ||
143 | default: | ||
144 | [NSException raise:NSInternalInconsistencyException format:@""]; | ||
145 | |||
146 | } | ||
147 | |||
148 | size_ = size; | ||
149 | width_ = width; | ||
150 | height_ = height; | ||
151 | format_ = pixelFormat; | ||
152 | maxS_ = size.width / (float)width; | ||
153 | maxT_ = size.height / (float)height; | ||
154 | |||
155 | hasPremultipliedAlpha_ = NO; | ||
156 | } | ||
157 | return self; | ||
158 | } | ||
159 | |||
160 | - (void) releaseData:(void*)data | ||
161 | { | ||
162 | //Free data | ||
163 | free(data); | ||
164 | } | ||
165 | |||
166 | - (void*) keepData:(void*)data length:(NSUInteger)length | ||
167 | { | ||
168 | //The texture data mustn't be saved becuase it isn't a mutable texture. | ||
169 | return data; | ||
170 | } | ||
171 | |||
172 | - (void) dealloc | ||
173 | { | ||
174 | CCLOGINFO(@"cocos2d: deallocing %@", self); | ||
175 | if(name_) | ||
176 | glDeleteTextures(1, &name_); | ||
177 | |||
178 | [super dealloc]; | ||
179 | } | ||
180 | |||
181 | - (NSString*) description | ||
182 | { | ||
183 | return [NSString stringWithFormat:@"<%@ = %08X | Name = %i | Dimensions = %ix%i | Coordinates = (%.2f, %.2f)>", [self class], self, name_, width_, height_, maxS_, maxT_]; | ||
184 | } | ||
185 | |||
186 | -(CGSize) contentSize | ||
187 | { | ||
188 | CGSize ret; | ||
189 | ret.width = size_.width / CC_CONTENT_SCALE_FACTOR(); | ||
190 | ret.height = size_.height / CC_CONTENT_SCALE_FACTOR(); | ||
191 | |||
192 | return ret; | ||
193 | } | ||
194 | @end | ||
195 | |||
196 | #pragma mark - | ||
197 | #pragma mark CCTexture2D - Image | ||
198 | |||
199 | @implementation CCTexture2D (Image) | ||
200 | #ifdef __IPHONE_OS_VERSION_MAX_ALLOWED | ||
201 | - (id) initWithImage:(UIImage *)uiImage | ||
202 | #elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) | ||
203 | - (id) initWithImage:(CGImageRef)CGImage | ||
204 | #endif | ||
205 | { | ||
206 | NSUInteger POTWide, POTHigh; | ||
207 | CGContextRef context = nil; | ||
208 | void* data = nil;; | ||
209 | CGColorSpaceRef colorSpace; | ||
210 | void* tempData; | ||
211 | unsigned int* inPixel32; | ||
212 | unsigned short* outPixel16; | ||
213 | BOOL hasAlpha; | ||
214 | CGImageAlphaInfo info; | ||
215 | CGSize imageSize; | ||
216 | CCTexture2DPixelFormat pixelFormat; | ||
217 | |||
218 | #ifdef __IPHONE_OS_VERSION_MAX_ALLOWED | ||
219 | CGImageRef CGImage = uiImage.CGImage; | ||
220 | #endif | ||
221 | |||
222 | if(CGImage == NULL) { | ||
223 | CCLOG(@"cocos2d: CCTexture2D. Can't create Texture. UIImage is nil"); | ||
224 | [self release]; | ||
225 | return nil; | ||
226 | } | ||
227 | |||
228 | CCConfiguration *conf = [CCConfiguration sharedConfiguration]; | ||
229 | |||
230 | #if CC_TEXTURE_NPOT_SUPPORT | ||
231 | if( [conf supportsNPOT] ) { | ||
232 | POTWide = CGImageGetWidth(CGImage); | ||
233 | POTHigh = CGImageGetHeight(CGImage); | ||
234 | |||
235 | } else | ||
236 | #endif | ||
237 | { | ||
238 | POTWide = ccNextPOT(CGImageGetWidth(CGImage)); | ||
239 | POTHigh = ccNextPOT(CGImageGetHeight(CGImage)); | ||
240 | } | ||
241 | |||
242 | NSUInteger maxTextureSize = [conf maxTextureSize]; | ||
243 | if( POTHigh > maxTextureSize || POTWide > maxTextureSize ) { | ||
244 | CCLOG(@"cocos2d: WARNING: Image (%lu x %lu) is bigger than the supported %ld x %ld", | ||
245 | (long)POTWide, (long)POTHigh, | ||
246 | (long)maxTextureSize, (long)maxTextureSize); | ||
247 | [self release]; | ||
248 | return nil; | ||
249 | } | ||
250 | |||
251 | info = CGImageGetAlphaInfo(CGImage); | ||
252 | hasAlpha = ((info == kCGImageAlphaPremultipliedLast) || (info == kCGImageAlphaPremultipliedFirst) || (info == kCGImageAlphaLast) || (info == kCGImageAlphaFirst) ? YES : NO); | ||
253 | |||
254 | size_t bpp = CGImageGetBitsPerComponent(CGImage); | ||
255 | colorSpace = CGImageGetColorSpace(CGImage); | ||
256 | |||
257 | if(colorSpace) { | ||
258 | if(hasAlpha || bpp >= 8) | ||
259 | pixelFormat = defaultAlphaPixelFormat_; | ||
260 | else { | ||
261 | CCLOG(@"cocos2d: CCTexture2D: Using RGB565 texture since image has no alpha"); | ||
262 | pixelFormat = kCCTexture2DPixelFormat_RGB565; | ||
263 | } | ||
264 | } else { | ||
265 | // NOTE: No colorspace means a mask image | ||
266 | CCLOG(@"cocos2d: CCTexture2D: Using A8 texture since image is a mask"); | ||
267 | pixelFormat = kCCTexture2DPixelFormat_A8; | ||
268 | } | ||
269 | |||
270 | imageSize = CGSizeMake(CGImageGetWidth(CGImage), CGImageGetHeight(CGImage)); | ||
271 | |||
272 | // Create the bitmap graphics context | ||
273 | |||
274 | switch(pixelFormat) { | ||
275 | case kCCTexture2DPixelFormat_RGBA8888: | ||
276 | case kCCTexture2DPixelFormat_RGBA4444: | ||
277 | case kCCTexture2DPixelFormat_RGB5A1: | ||
278 | colorSpace = CGColorSpaceCreateDeviceRGB(); | ||
279 | data = malloc(POTHigh * POTWide * 4); | ||
280 | info = hasAlpha ? kCGImageAlphaPremultipliedLast : kCGImageAlphaNoneSkipLast; | ||
281 | // info = kCGImageAlphaPremultipliedLast; // issue #886. This patch breaks BMP images. | ||
282 | context = CGBitmapContextCreate(data, POTWide, POTHigh, 8, 4 * POTWide, colorSpace, info | kCGBitmapByteOrder32Big); | ||
283 | CGColorSpaceRelease(colorSpace); | ||
284 | break; | ||
285 | |||
286 | case kCCTexture2DPixelFormat_RGB565: | ||
287 | colorSpace = CGColorSpaceCreateDeviceRGB(); | ||
288 | data = malloc(POTHigh * POTWide * 4); | ||
289 | info = kCGImageAlphaNoneSkipLast; | ||
290 | context = CGBitmapContextCreate(data, POTWide, POTHigh, 8, 4 * POTWide, colorSpace, info | kCGBitmapByteOrder32Big); | ||
291 | CGColorSpaceRelease(colorSpace); | ||
292 | break; | ||
293 | case kCCTexture2DPixelFormat_A8: | ||
294 | data = malloc(POTHigh * POTWide); | ||
295 | info = kCGImageAlphaOnly; | ||
296 | context = CGBitmapContextCreate(data, POTWide, POTHigh, 8, POTWide, NULL, info); | ||
297 | break; | ||
298 | default: | ||
299 | [NSException raise:NSInternalInconsistencyException format:@"Invalid pixel format"]; | ||
300 | } | ||
301 | |||
302 | |||
303 | CGContextClearRect(context, CGRectMake(0, 0, POTWide, POTHigh)); | ||
304 | CGContextTranslateCTM(context, 0, POTHigh - imageSize.height); | ||
305 | CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(CGImage), CGImageGetHeight(CGImage)), CGImage); | ||
306 | |||
307 | // Repack the pixel data into the right format | ||
308 | |||
309 | if(pixelFormat == kCCTexture2DPixelFormat_RGB565) { | ||
310 | //Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGGBBBBB" | ||
311 | tempData = malloc(POTHigh * POTWide * 2); | ||
312 | inPixel32 = (unsigned int*)data; | ||
313 | outPixel16 = (unsigned short*)tempData; | ||
314 | for(unsigned int i = 0; i < POTWide * POTHigh; ++i, ++inPixel32) | ||
315 | *outPixel16++ = ((((*inPixel32 >> 0) & 0xFF) >> 3) << 11) | ((((*inPixel32 >> 8) & 0xFF) >> 2) << 5) | ((((*inPixel32 >> 16) & 0xFF) >> 3) << 0); | ||
316 | free(data); | ||
317 | data = tempData; | ||
318 | |||
319 | } | ||
320 | else if (pixelFormat == kCCTexture2DPixelFormat_RGBA4444) { | ||
321 | //Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRGGGGBBBBAAAA" | ||
322 | tempData = malloc(POTHigh * POTWide * 2); | ||
323 | inPixel32 = (unsigned int*)data; | ||
324 | outPixel16 = (unsigned short*)tempData; | ||
325 | for(unsigned int i = 0; i < POTWide * POTHigh; ++i, ++inPixel32) | ||
326 | *outPixel16++ = | ||
327 | ((((*inPixel32 >> 0) & 0xFF) >> 4) << 12) | // R | ||
328 | ((((*inPixel32 >> 8) & 0xFF) >> 4) << 8) | // G | ||
329 | ((((*inPixel32 >> 16) & 0xFF) >> 4) << 4) | // B | ||
330 | ((((*inPixel32 >> 24) & 0xFF) >> 4) << 0); // A | ||
331 | |||
332 | |||
333 | free(data); | ||
334 | data = tempData; | ||
335 | |||
336 | } | ||
337 | else if (pixelFormat == kCCTexture2DPixelFormat_RGB5A1) { | ||
338 | //Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGBBBBBA" | ||
339 | tempData = malloc(POTHigh * POTWide * 2); | ||
340 | inPixel32 = (unsigned int*)data; | ||
341 | outPixel16 = (unsigned short*)tempData; | ||
342 | for(unsigned int i = 0; i < POTWide * POTHigh; ++i, ++inPixel32) | ||
343 | *outPixel16++ = | ||
344 | ((((*inPixel32 >> 0) & 0xFF) >> 3) << 11) | // R | ||
345 | ((((*inPixel32 >> 8) & 0xFF) >> 3) << 6) | // G | ||
346 | ((((*inPixel32 >> 16) & 0xFF) >> 3) << 1) | // B | ||
347 | ((((*inPixel32 >> 24) & 0xFF) >> 7) << 0); // A | ||
348 | |||
349 | |||
350 | free(data); | ||
351 | data = tempData; | ||
352 | } | ||
353 | self = [self initWithData:data pixelFormat:pixelFormat pixelsWide:POTWide pixelsHigh:POTHigh contentSize:imageSize]; | ||
354 | |||
355 | // should be after calling super init | ||
356 | hasPremultipliedAlpha_ = (info == kCGImageAlphaPremultipliedLast || info == kCGImageAlphaPremultipliedFirst); | ||
357 | |||
358 | CGContextRelease(context); | ||
359 | [self releaseData:data]; | ||
360 | |||
361 | return self; | ||
362 | } | ||
363 | @end | ||
364 | |||
365 | #pragma mark - | ||
366 | #pragma mark CCTexture2D - Text | ||
367 | |||
368 | @implementation CCTexture2D (Text) | ||
369 | |||
370 | #ifdef __IPHONE_OS_VERSION_MAX_ALLOWED | ||
371 | |||
372 | - (id) initWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment lineBreakMode:(CCLineBreakMode)lineBreakMode font:(id)uifont | ||
373 | { | ||
374 | NSAssert( uifont, @"Invalid font"); | ||
375 | |||
376 | NSUInteger POTWide = ccNextPOT(dimensions.width); | ||
377 | NSUInteger POTHigh = ccNextPOT(dimensions.height); | ||
378 | unsigned char* data; | ||
379 | |||
380 | CGContextRef context; | ||
381 | CGColorSpaceRef colorSpace; | ||
382 | |||
383 | #if USE_TEXT_WITH_A8_TEXTURES | ||
384 | data = calloc(POTHigh, POTWide); | ||
385 | #else | ||
386 | data = calloc(POTHigh, POTWide * 2); | ||
387 | #endif | ||
388 | |||
389 | colorSpace = CGColorSpaceCreateDeviceGray(); | ||
390 | context = CGBitmapContextCreate(data, POTWide, POTHigh, 8, POTWide, colorSpace, kCGImageAlphaNone); | ||
391 | CGColorSpaceRelease(colorSpace); | ||
392 | |||
393 | if( ! context ) { | ||
394 | free(data); | ||
395 | [self release]; | ||
396 | return nil; | ||
397 | } | ||
398 | |||
399 | CGContextSetGrayFillColor(context, 1.0f, 1.0f); | ||
400 | CGContextTranslateCTM(context, 0.0f, POTHigh); | ||
401 | CGContextScaleCTM(context, 1.0f, -1.0f); //NOTE: NSString draws in UIKit referential i.e. renders upside-down compared to CGBitmapContext referential | ||
402 | |||
403 | UIGraphicsPushContext(context); | ||
404 | |||
405 | // normal fonts | ||
406 | if( [uifont isKindOfClass:[UIFont class] ] ) | ||
407 | [string drawInRect:CGRectMake(0, 0, dimensions.width, dimensions.height) withFont:uifont lineBreakMode:lineBreakMode alignment:alignment]; | ||
408 | |||
409 | #if CC_FONT_LABEL_SUPPORT | ||
410 | else // ZFont class | ||
411 | [string drawInRect:CGRectMake(0, 0, dimensions.width, dimensions.height) withZFont:uifont lineBreakMode:lineBreakMode alignment:alignment]; | ||
412 | #endif | ||
413 | |||
414 | UIGraphicsPopContext(); | ||
415 | |||
416 | #if USE_TEXT_WITH_A8_TEXTURES | ||
417 | self = [self initWithData:data pixelFormat:kCCTexture2DPixelFormat_A8 pixelsWide:POTWide pixelsHigh:POTHigh contentSize:dimensions]; | ||
418 | |||
419 | #else // ! USE_TEXT_WITH_A8_TEXTURES | ||
420 | NSUInteger textureSize = POTWide*POTHigh; | ||
421 | unsigned short *la88_data = (unsigned short*)data; | ||
422 | for(int i = textureSize-1; i>=0; i--) //Convert A8 to AI88 | ||
423 | la88_data[i] = (data[i] << 8) | 0xff; | ||
424 | |||
425 | self = [self initWithData:data pixelFormat:kCCTexture2DPixelFormat_AI88 pixelsWide:POTWide pixelsHigh:POTHigh contentSize:dimensions]; | ||
426 | #endif // ! USE_TEXT_WITH_A8_TEXTURES | ||
427 | |||
428 | CGContextRelease(context); | ||
429 | [self releaseData:data]; | ||
430 | |||
431 | return self; | ||
432 | } | ||
433 | |||
434 | |||
435 | |||
436 | #elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) | ||
437 | |||
438 | - (id) initWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment attributedString:(NSAttributedString*)stringWithAttributes | ||
439 | { | ||
440 | NSAssert( stringWithAttributes, @"Invalid stringWithAttributes"); | ||
441 | |||
442 | NSUInteger POTWide = ccNextPOT(dimensions.width); | ||
443 | NSUInteger POTHigh = ccNextPOT(dimensions.height); | ||
444 | unsigned char* data; | ||
445 | |||
446 | NSSize realDimensions = [stringWithAttributes size]; | ||
447 | |||
448 | //Alignment | ||
449 | float xPadding = 0; | ||
450 | |||
451 | // Mac crashes if the width or height is 0 | ||
452 | if( realDimensions.width > 0 && realDimensions.height > 0 ) { | ||
453 | switch (alignment) { | ||
454 | case CCTextAlignmentLeft: xPadding = 0; break; | ||
455 | case CCTextAlignmentCenter: xPadding = (dimensions.width-realDimensions.width)/2.0f; break; | ||
456 | case CCTextAlignmentRight: xPadding = dimensions.width-realDimensions.width; break; | ||
457 | default: break; | ||
458 | } | ||
459 | |||
460 | //Disable antialias | ||
461 | [[NSGraphicsContext currentContext] setShouldAntialias:NO]; | ||
462 | |||
463 | NSImage *image = [[NSImage alloc] initWithSize:NSMakeSize(POTWide, POTHigh)]; | ||
464 | [image lockFocus]; | ||
465 | |||
466 | [stringWithAttributes drawAtPoint:NSMakePoint(xPadding, POTHigh-dimensions.height)]; // draw at offset position | ||
467 | |||
468 | NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithFocusedViewRect:NSMakeRect (0.0f, 0.0f, POTWide, POTHigh)]; | ||
469 | [image unlockFocus]; | ||
470 | |||
471 | data = (unsigned char*) [bitmap bitmapData]; //Use the same buffer to improve the performance. | ||
472 | |||
473 | NSUInteger textureSize = POTWide*POTHigh; | ||
474 | for(int i = 0; i<textureSize; i++) //Convert RGBA8888 to A8 | ||
475 | data[i] = data[i*4+3]; | ||
476 | |||
477 | data = [self keepData:data length:textureSize]; | ||
478 | self = [self initWithData:data pixelFormat:kCCTexture2DPixelFormat_A8 pixelsWide:POTWide pixelsHigh:POTHigh contentSize:dimensions]; | ||
479 | |||
480 | [bitmap release]; | ||
481 | [image release]; | ||
482 | |||
483 | } else { | ||
484 | [self release]; | ||
485 | return nil; | ||
486 | } | ||
487 | |||
488 | return self; | ||
489 | } | ||
490 | #endif // __MAC_OS_X_VERSION_MAX_ALLOWED | ||
491 | |||
492 | - (id) initWithString:(NSString*)string fontName:(NSString*)name fontSize:(CGFloat)size | ||
493 | { | ||
494 | CGSize dim; | ||
495 | |||
496 | #ifdef __IPHONE_OS_VERSION_MAX_ALLOWED | ||
497 | id font; | ||
498 | font = [UIFont fontWithName:name size:size]; | ||
499 | if( font ) | ||
500 | dim = [string sizeWithFont:font]; | ||
501 | |||
502 | #if CC_FONT_LABEL_SUPPORT | ||
503 | if( ! font ){ | ||
504 | font = [[FontManager sharedManager] zFontWithName:name pointSize:size]; | ||
505 | if (font) | ||
506 | dim = [string sizeWithZFont:font]; | ||
507 | } | ||
508 | #endif // CC_FONT_LABEL_SUPPORT | ||
509 | |||
510 | if( ! font ) { | ||
511 | CCLOG(@"cocos2d: Unable to load font %@", name); | ||
512 | [self release]; | ||
513 | return nil; | ||
514 | } | ||
515 | |||
516 | return [self initWithString:string dimensions:dim alignment:CCTextAlignmentCenter lineBreakMode:UILineBreakModeWordWrap font:font]; | ||
517 | |||
518 | #elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) | ||
519 | { | ||
520 | |||
521 | NSFont *font = [[NSFontManager sharedFontManager] | ||
522 | fontWithFamily:name | ||
523 | traits:NSUnboldFontMask | NSUnitalicFontMask | ||
524 | weight:0 | ||
525 | size:size]; | ||
526 | |||
527 | NSDictionary *dict = [NSDictionary dictionaryWithObject:font forKey:NSFontAttributeName]; | ||
528 | |||
529 | NSAttributedString *stringWithAttributes = [[[NSAttributedString alloc] initWithString:string attributes:dict] autorelease]; | ||
530 | |||
531 | dim = NSSizeToCGSize( [stringWithAttributes size] ); | ||
532 | |||
533 | return [self initWithString:string dimensions:dim alignment:CCTextAlignmentCenter attributedString:stringWithAttributes]; | ||
534 | } | ||
535 | #endif // __MAC_OS_X_VERSION_MAX_ALLOWED | ||
536 | |||
537 | } | ||
538 | |||
539 | - (id) initWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment fontName:(NSString*)name fontSize:(CGFloat)size | ||
540 | { | ||
541 | return [self initWithString:string dimensions:dimensions alignment:alignment lineBreakMode:CCLineBreakModeWordWrap fontName:name fontSize:size]; | ||
542 | } | ||
543 | |||
544 | - (id) initWithString:(NSString*)string dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment lineBreakMode:(CCLineBreakMode)lineBreakMode fontName:(NSString*)name fontSize:(CGFloat)size | ||
545 | { | ||
546 | #ifdef __IPHONE_OS_VERSION_MAX_ALLOWED | ||
547 | id uifont = nil; | ||
548 | |||
549 | uifont = [UIFont fontWithName:name size:size]; | ||
550 | |||
551 | #if CC_FONT_LABEL_SUPPORT | ||
552 | if( ! uifont ) | ||
553 | uifont = [[FontManager sharedManager] zFontWithName:name pointSize:size]; | ||
554 | #endif // CC_FONT_LABEL_SUPPORT | ||
555 | if( ! uifont ) { | ||
556 | CCLOG(@"cocos2d: Texture2d: Invalid Font: %@. Verify the .ttf name", name); | ||
557 | [self release]; | ||
558 | return nil; | ||
559 | } | ||
560 | |||
561 | return [self initWithString:string dimensions:dimensions alignment:alignment lineBreakMode:lineBreakMode font:uifont]; | ||
562 | |||
563 | #elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) | ||
564 | |||
565 | NSAssert( lineBreakMode == CCLineBreakModeWordWrap, @"CCTexture2D: unsupported line break mode for Mac OS X"); | ||
566 | |||
567 | //String with attributes | ||
568 | NSAttributedString *stringWithAttributes = | ||
569 | [[[NSAttributedString alloc] initWithString:string | ||
570 | attributes:[NSDictionary dictionaryWithObject:[[NSFontManager sharedFontManager] | ||
571 | fontWithFamily:name | ||
572 | traits:NSUnboldFontMask | NSUnitalicFontMask | ||
573 | weight:0 | ||
574 | size:size] | ||
575 | forKey:NSFontAttributeName] | ||
576 | ] | ||
577 | autorelease]; | ||
578 | |||
579 | return [self initWithString:string dimensions:dimensions alignment:alignment attributedString:stringWithAttributes]; | ||
580 | |||
581 | #endif // Mac | ||
582 | } | ||
583 | @end | ||
584 | |||
585 | #pragma mark - | ||
586 | #pragma mark CCTexture2D - PVRSupport | ||
587 | |||
588 | @implementation CCTexture2D (PVRSupport) | ||
589 | |||
590 | // By default PVR images are treated as if they don't have the alpha channel premultiplied | ||
591 | static BOOL PVRHaveAlphaPremultiplied_ = NO; | ||
592 | |||
593 | #ifdef __IPHONE_OS_VERSION_MAX_ALLOWED | ||
594 | -(id) initWithPVRTCData: (const void*)data level:(int)level bpp:(int)bpp hasAlpha:(BOOL)hasAlpha length:(int)length pixelFormat:(CCTexture2DPixelFormat)pixelFormat | ||
595 | { | ||
596 | // GLint saveName; | ||
597 | |||
598 | if( ! [[CCConfiguration sharedConfiguration] supportsPVRTC] ) { | ||
599 | CCLOG(@"cocos2d: WARNING: PVRTC images is not supported"); | ||
600 | [self release]; | ||
601 | return nil; | ||
602 | } | ||
603 | |||
604 | if((self = [super init])) { | ||
605 | glGenTextures(1, &name_); | ||
606 | glBindTexture(GL_TEXTURE_2D, name_); | ||
607 | |||
608 | [self setAntiAliasTexParameters]; | ||
609 | |||
610 | GLenum format; | ||
611 | GLsizei size = length * length * bpp / 8; | ||
612 | if(hasAlpha) | ||
613 | format = (bpp == 4) ? GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG : GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; | ||
614 | else | ||
615 | format = (bpp == 4) ? GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG : GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG; | ||
616 | |||
617 | if(size < 32) | ||
618 | size = 32; | ||
619 | |||
620 | glCompressedTexImage2D(GL_TEXTURE_2D, level, format, length, length, 0, size, data); | ||
621 | |||
622 | size_ = CGSizeMake(length, length); | ||
623 | width_ = length; | ||
624 | height_ = length; | ||
625 | maxS_ = 1.0f; | ||
626 | maxT_ = 1.0f; | ||
627 | hasPremultipliedAlpha_ = PVRHaveAlphaPremultiplied_; | ||
628 | format_ = pixelFormat; | ||
629 | } | ||
630 | return self; | ||
631 | } | ||
632 | #endif // __IPHONE_OS_VERSION_MAX_ALLOWED | ||
633 | |||
634 | -(id) initWithPVRFile: (NSString*) file | ||
635 | { | ||
636 | if( (self = [super init]) ) { | ||
637 | CCTexturePVR *pvr = [[CCTexturePVR alloc] initWithContentsOfFile:file]; | ||
638 | if( pvr ) { | ||
639 | pvr.retainName = YES; // don't dealloc texture on release | ||
640 | |||
641 | name_ = pvr.name; // texture id | ||
642 | maxS_ = 1; // only POT texture are supported | ||
643 | maxT_ = 1; | ||
644 | width_ = pvr.width; | ||
645 | height_ = pvr.height; | ||
646 | size_ = CGSizeMake(width_, height_); | ||
647 | hasPremultipliedAlpha_ = PVRHaveAlphaPremultiplied_; | ||
648 | format_ = pvr.format; | ||
649 | |||
650 | [pvr release]; | ||
651 | |||
652 | [self setAntiAliasTexParameters]; | ||
653 | } else { | ||
654 | |||
655 | CCLOG(@"cocos2d: Couldn't load PVR image: %@", file); | ||
656 | [self release]; | ||
657 | return nil; | ||
658 | } | ||
659 | } | ||
660 | return self; | ||
661 | } | ||
662 | |||
663 | +(void) PVRImagesHavePremultipliedAlpha:(BOOL)haveAlphaPremultiplied | ||
664 | { | ||
665 | PVRHaveAlphaPremultiplied_ = haveAlphaPremultiplied; | ||
666 | } | ||
667 | @end | ||
668 | |||
669 | #pragma mark - | ||
670 | #pragma mark CCTexture2D - Drawing | ||
671 | |||
672 | @implementation CCTexture2D (Drawing) | ||
673 | |||
674 | - (void) drawAtPoint:(CGPoint)point | ||
675 | { | ||
676 | GLfloat coordinates[] = { 0.0f, maxT_, | ||
677 | maxS_, maxT_, | ||
678 | 0.0f, 0.0f, | ||
679 | maxS_, 0.0f }; | ||
680 | GLfloat width = (GLfloat)width_ * maxS_, | ||
681 | height = (GLfloat)height_ * maxT_; | ||
682 | |||
683 | GLfloat vertices[] = { point.x, point.y, 0.0f, | ||
684 | width + point.x, point.y, 0.0f, | ||
685 | point.x, height + point.y, 0.0f, | ||
686 | width + point.x, height + point.y, 0.0f }; | ||
687 | |||
688 | glBindTexture(GL_TEXTURE_2D, name_); | ||
689 | glVertexPointer(3, GL_FLOAT, 0, vertices); | ||
690 | glTexCoordPointer(2, GL_FLOAT, 0, coordinates); | ||
691 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | ||
692 | } | ||
693 | |||
694 | |||
695 | - (void) drawInRect:(CGRect)rect | ||
696 | { | ||
697 | GLfloat coordinates[] = { 0.0f, maxT_, | ||
698 | maxS_, maxT_, | ||
699 | 0.0f, 0.0f, | ||
700 | maxS_, 0.0f }; | ||
701 | GLfloat vertices[] = { rect.origin.x, rect.origin.y, /*0.0f,*/ | ||
702 | rect.origin.x + rect.size.width, rect.origin.y, /*0.0f,*/ | ||
703 | rect.origin.x, rect.origin.y + rect.size.height, /*0.0f,*/ | ||
704 | rect.origin.x + rect.size.width, rect.origin.y + rect.size.height, /*0.0f*/ }; | ||
705 | |||
706 | glBindTexture(GL_TEXTURE_2D, name_); | ||
707 | glVertexPointer(2, GL_FLOAT, 0, vertices); | ||
708 | glTexCoordPointer(2, GL_FLOAT, 0, coordinates); | ||
709 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | ||
710 | } | ||
711 | |||
712 | @end | ||
713 | |||
714 | |||
715 | #pragma mark - | ||
716 | #pragma mark CCTexture2D - GLFilter | ||
717 | |||
718 | // | ||
719 | // Use to apply MIN/MAG filter | ||
720 | // | ||
721 | @implementation CCTexture2D (GLFilter) | ||
722 | |||
723 | -(void) generateMipmap | ||
724 | { | ||
725 | NSAssert( width_ == ccNextPOT(width_) && height_ == ccNextPOT(height_), @"Mimpap texture only works in POT textures"); | ||
726 | glBindTexture( GL_TEXTURE_2D, name_ ); | ||
727 | ccglGenerateMipmap(GL_TEXTURE_2D); | ||
728 | } | ||
729 | |||
730 | -(void) setTexParameters: (ccTexParams*) texParams | ||
731 | { | ||
732 | NSAssert( (width_ == ccNextPOT(width_) && height_ == ccNextPOT(height_)) || | ||
733 | (texParams->wrapS == GL_CLAMP_TO_EDGE && texParams->wrapT == GL_CLAMP_TO_EDGE), | ||
734 | @"GL_CLAMP_TO_EDGE should be used in NPOT textures"); | ||
735 | glBindTexture( GL_TEXTURE_2D, name_ ); | ||
736 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, texParams->minFilter ); | ||
737 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, texParams->magFilter ); | ||
738 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, texParams->wrapS ); | ||
739 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, texParams->wrapT ); | ||
740 | } | ||
741 | |||
742 | -(void) setAliasTexParameters | ||
743 | { | ||
744 | ccTexParams texParams = { GL_NEAREST, GL_NEAREST, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE }; | ||
745 | [self setTexParameters: &texParams]; | ||
746 | } | ||
747 | |||
748 | -(void) setAntiAliasTexParameters | ||
749 | { | ||
750 | ccTexParams texParams = { GL_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE }; | ||
751 | [self setTexParameters: &texParams]; | ||
752 | } | ||
753 | @end | ||
754 | |||
755 | |||
756 | #pragma mark - | ||
757 | #pragma mark CCTexture2D - Pixel Format | ||
758 | |||
759 | // | ||
760 | // Texture options for images that contains alpha | ||
761 | // | ||
762 | @implementation CCTexture2D (PixelFormat) | ||
763 | +(void) setDefaultAlphaPixelFormat:(CCTexture2DPixelFormat)format | ||
764 | { | ||
765 | defaultAlphaPixelFormat_ = format; | ||
766 | } | ||
767 | |||
768 | +(CCTexture2DPixelFormat) defaultAlphaPixelFormat | ||
769 | { | ||
770 | return defaultAlphaPixelFormat_; | ||
771 | } | ||
772 | |||
773 | -(NSUInteger) bitsPerPixelForFormat | ||
774 | { | ||
775 | NSUInteger ret=0; | ||
776 | |||
777 | switch (format_) { | ||
778 | case kCCTexture2DPixelFormat_RGBA8888: | ||
779 | ret = 32; | ||
780 | break; | ||
781 | case kCCTexture2DPixelFormat_RGB565: | ||
782 | ret = 16; | ||
783 | break; | ||
784 | case kCCTexture2DPixelFormat_A8: | ||
785 | ret = 8; | ||
786 | break; | ||
787 | case kCCTexture2DPixelFormat_RGBA4444: | ||
788 | ret = 16; | ||
789 | break; | ||
790 | case kCCTexture2DPixelFormat_RGB5A1: | ||
791 | ret = 16; | ||
792 | break; | ||
793 | case kCCTexture2DPixelFormat_PVRTC4: | ||
794 | ret = 4; | ||
795 | break; | ||
796 | case kCCTexture2DPixelFormat_PVRTC2: | ||
797 | ret = 2; | ||
798 | break; | ||
799 | case kCCTexture2DPixelFormat_I8: | ||
800 | ret = 8; | ||
801 | break; | ||
802 | case kCCTexture2DPixelFormat_AI88: | ||
803 | ret = 16; | ||
804 | break; | ||
805 | default: | ||
806 | ret = -1; | ||
807 | NSAssert1(NO , @"bitsPerPixelForFormat: %ld, unrecognised pixel format", (long)format_); | ||
808 | CCLOG(@"bitsPerPixelForFormat: %ld, cannot give useful result", (long)format_); | ||
809 | break; | ||
810 | } | ||
811 | return ret; | ||
812 | } | ||
813 | @end | ||
814 | |||