diff options
| author | Starla Insigna <starla4444@gmail.com> | 2011-07-30 11:19:14 -0400 |
|---|---|---|
| committer | Starla Insigna <starla4444@gmail.com> | 2011-07-30 11:19:14 -0400 |
| commit | 9cd57b731ab1c666d4a1cb725538fdc137763d12 (patch) | |
| tree | 5bac45ae5157a1cb10c6e45500cbf72789917980 /libs/cocos2d/CCTexture2D.m | |
| download | cartcollect-9cd57b731ab1c666d4a1cb725538fdc137763d12.tar.gz cartcollect-9cd57b731ab1c666d4a1cb725538fdc137763d12.tar.bz2 cartcollect-9cd57b731ab1c666d4a1cb725538fdc137763d12.zip | |
Initial commit (version 0.2.1)
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 | |||
