diff --git a/cocos2d/CCLabelBMFont.h b/cocos2d/CCLabelBMFont.h index fc0735966ae..54fe6657c9b 100644 --- a/cocos2d/CCLabelBMFont.h +++ b/cocos2d/CCLabelBMFont.h @@ -40,8 +40,6 @@ enum { kCCLabelAutomaticWidth = -1, }; -struct _KerningHashElement; - /** @struct ccBMFontDef BMFont definition */ @@ -73,6 +71,22 @@ typedef struct _BMFontPadding { int bottom; } ccBMFontPadding; +#pragma mark - Hash Element +typedef struct _FontDefHashElement +{ + NSUInteger key; // key. Font Unicode value + ccBMFontDef fontDef; // font definition + UT_hash_handle hh; +} tFontDefHashElement; + +// Equal function for targetSet. +typedef struct _KerningHashElement +{ + int key; // key for the hash. 16-bit for 1st element, 16-bit for 2nd element + int amount; + UT_hash_handle hh; +} tKerningHashElement; +#pragma mark - /** CCBMFontConfiguration has parsed configuration of the the .fnt file @since v0.8 @@ -81,21 +95,21 @@ typedef struct _BMFontPadding { { // atlas name NSString *atlasName_; - + // XXX: Creating a public interface so that the bitmapFontArray[] is accesible @public - + // BMFont definitions - struct _FontDefHashElement *fontDefDictionary_; - + tFontDefHashElement *fontDefDictionary_; + // FNTConfig: Common Height. Should be signed (issue #1343) NSInteger commonHeight_; - + // Padding ccBMFontPadding padding_; - + // values for kerning - struct _KerningHashElement *kerningDictionary_; + tKerningHashElement *kerningDictionary_; } // atlasName @@ -109,7 +123,7 @@ typedef struct _BMFontPadding { /** CCLabelBMFont is a subclass of CCSpriteBatchNode - + Features: - Treats each character like a CCSprite. This means that each individual character can be: - rotated @@ -120,22 +134,22 @@ typedef struct _BMFontPadding { - It can be used as part of a menu item. - anchorPoint can be used to align the "label" - Supports AngelCode text format - + Limitations: - All inner characters are using an anchorPoint of (0.5f, 0.5f) and it is not recommend to change it because it might affect the rendering - + CCLabelBMFont implements the protocol CCLabelProtocol, like CCLabel and CCLabelAtlas. CCLabelBMFont has the flexibility of CCLabel, the speed of CCLabelAtlas and all the features of CCSprite. If in doubt, use CCLabelBMFont instead of CCLabelAtlas / CCLabel. - + Supported editors: - http://glyphdesigner.71squared.com/ - http://www.bmglyph.com/ - http://www.n4te.com/hiero/hiero.jnlp - http://slick.cokeandcode.com/demos/hiero.jnlp - http://www.angelcode.com/products/bmfont/ - + @since v0.8 */ @@ -146,16 +160,16 @@ typedef struct _BMFontPadding { // name of fntFile NSString *fntFile_; - + // initial string without line breaks NSString *initialString_; // max width until a line break is added float width_; // alignment of all lines CCTextAlignment alignment_; - + CCBMFontConfiguration *configuration_; - + // texture RGBA GLubyte opacity_; ccColor3B color_; diff --git a/cocos2d/CCLabelBMFont.m b/cocos2d/CCLabelBMFont.m index 371f70cf8e9..58a33dc83bc 100644 --- a/cocos2d/CCLabelBMFont.m +++ b/cocos2d/CCLabelBMFont.m @@ -52,17 +52,17 @@ CCBMFontConfiguration* FNTConfigLoadFile( NSString *fntFile) { CCBMFontConfiguration *ret = nil; - + if( configurations == nil ) configurations = [[NSMutableDictionary dictionaryWithCapacity:3] retain]; - + ret = [configurations objectForKey:fntFile]; if( ret == nil ) { ret = [CCBMFontConfiguration configurationWithFNTFile:fntFile]; if( ret ) [configurations setObject:ret forKey:fntFile]; } - + return ret; } @@ -71,28 +71,9 @@ void FNTConfigRemoveCache( void ) [configurations removeAllObjects]; } -#pragma mark - Hash Element - -// Equal function for targetSet. -typedef struct _KerningHashElement -{ - int key; // key for the hash. 16-bit for 1st element, 16-bit for 2nd element - int amount; - UT_hash_handle hh; -} tKerningHashElement; - - #pragma mark - #pragma mark BitmapFontConfiguration -typedef struct _FontDefHashElement -{ - NSUInteger key; // key. Font Unicode value - ccBMFontDef fontDef; // font definition - UT_hash_handle hh; -} tFontDefHashElement; - - @interface CCBMFontConfiguration () -(BOOL) parseConfigFile:(NSString*)controlFile; -(void) parseCharacterDefinition:(NSString*)line charDef:(ccBMFontDef*)characterDefinition; @@ -118,10 +99,10 @@ +(id) configurationWithFNTFile:(NSString*)FNTfile -(id) initWithFNTfile:(NSString*)fntFile { if((self=[super init])) { - + kerningDictionary_ = NULL; fontDefDictionary_ = NULL; - + if( ! [self parseConfigFile:fntFile] ) { [self release]; return nil; @@ -161,7 +142,7 @@ -(void) purgeFontDefDictionary -(void) purgeKerningDictionary { tKerningHashElement *current; - + while(kerningDictionary_) { current = kerningDictionary_; HASH_DEL(kerningDictionary_,current); @@ -174,21 +155,21 @@ - (BOOL)parseConfigFile:(NSString*)fntFile NSString *fullpath = [[CCFileUtils sharedFileUtils] fullPathFromRelativePath:fntFile]; NSError *error; NSString *contents = [NSString stringWithContentsOfFile:fullpath encoding:NSUTF8StringEncoding error:&error]; - + if( ! contents ) { NSLog(@"cocos2d: Error parsing FNTfile %@: %@", fntFile, error); return NO; } - + // Move all lines in the string, which are denoted by \n, into an array NSArray *lines = [[NSArray alloc] initWithArray:[contents componentsSeparatedByString:@"\n"]]; - + // Create an enumerator which we can use to move through the lines read from the control file NSEnumerator *nse = [lines objectEnumerator]; - + // Create a holder for each line we are going to work with NSString *line; - + // Loop through all the lines in the lines array processing each one while( (line = [nse nextObject]) ) { // parse spacing / padding @@ -216,9 +197,9 @@ - (BOOL)parseConfigFile:(NSString*)fntFile element->key = element->fontDef.charID; HASH_ADD_INT(fontDefDictionary_, key, element); } -// else if([line hasPrefix:@"kernings count"]) { -// [self parseKerningCapacity:line]; -// } + // else if([line hasPrefix:@"kernings count"]) { + // [self parseKerningCapacity:line]; + // } else if([line hasPrefix:@"kerning first"]) { [self parseKerningEntry:line]; } @@ -232,30 +213,30 @@ - (BOOL)parseConfigFile:(NSString*)fntFile -(void) parseImageFileName:(NSString*)line fntFile:(NSString*)fntFile { NSString *propertyValue = nil; - + // Break the values for this line up using = NSArray *values = [line componentsSeparatedByString:@"="]; - + // Get the enumerator for the array of components which has been created NSEnumerator *nse = [values objectEnumerator]; - + // We need to move past the first entry in the array before we start assigning values [nse nextObject]; - + // page ID. Sanity check propertyValue = [nse nextObject]; NSAssert( [propertyValue intValue] == 0, @"XXX: LabelBMFont only supports 1 page"); - + // file propertyValue = [nse nextObject]; NSArray *array = [propertyValue componentsSeparatedByString:@"\""]; propertyValue = [array objectAtIndex:1]; NSAssert(propertyValue,@"LabelBMFont file could not be found"); - + // Supports subdirectories NSString *dir = [fntFile stringByDeletingLastPathComponent]; atlasName_ = [dir stringByAppendingPathComponent:propertyValue]; - + [atlasName_ retain]; } @@ -269,62 +250,62 @@ -(void) parseInfoArguments:(NSString*)line NSArray *values = [line componentsSeparatedByString:@"="]; NSEnumerator *nse = [values objectEnumerator]; NSString *propertyValue = nil; - + // We need to move past the first entry in the array before we start assigning values [nse nextObject]; - + // face (ignore) [nse nextObject]; - + // size (ignore) [nse nextObject]; - + // bold (ignore) [nse nextObject]; - + // italic (ignore) [nse nextObject]; - + // charset (ignore) [nse nextObject]; - + // unicode (ignore) [nse nextObject]; - + // strechH (ignore) [nse nextObject]; - + // smooth (ignore) [nse nextObject]; - + // aa (ignore) [nse nextObject]; - + // padding (ignore) propertyValue = [nse nextObject]; { - + NSArray *paddingValues = [propertyValue componentsSeparatedByString:@","]; NSEnumerator *paddingEnum = [paddingValues objectEnumerator]; // padding top propertyValue = [paddingEnum nextObject]; padding_.top = [propertyValue intValue]; - + // padding right propertyValue = [paddingEnum nextObject]; padding_.right = [propertyValue intValue]; - + // padding bottom propertyValue = [paddingEnum nextObject]; padding_.bottom = [propertyValue intValue]; - + // padding left propertyValue = [paddingEnum nextObject]; padding_.left = [propertyValue intValue]; - + CCLOG(@"cocos2d: padding: %d,%d,%d,%d", padding_.left, padding_.top, padding_.right, padding_.bottom); } - + // spacing (ignore) [nse nextObject]; } @@ -338,30 +319,30 @@ -(void) parseCommonArguments:(NSString*)line NSArray *values = [line componentsSeparatedByString:@"="]; NSEnumerator *nse = [values objectEnumerator]; NSString *propertyValue = nil; - + // We need to move past the first entry in the array before we start assigning values [nse nextObject]; - + // Character ID propertyValue = [nse nextObject]; commonHeight_ = [propertyValue intValue]; - + // base (ignore) [nse nextObject]; - - + + // scaleW. sanity check propertyValue = [nse nextObject]; NSAssert( [propertyValue intValue] <= [[CCConfiguration sharedConfiguration] maxTextureSize], @"CCLabelBMFont: page can't be larger than supported"); - + // scaleH. sanity check propertyValue = [nse nextObject]; NSAssert( [propertyValue intValue] <= [[CCConfiguration sharedConfiguration] maxTextureSize], @"CCLabelBMFont: page can't be larger than supported"); - + // pages. sanity check propertyValue = [nse nextObject]; NSAssert( [propertyValue intValue] == 1, @"CCBitfontAtlas: only supports 1 page"); - + // packed (ignore) What does this mean ?? } - (void)parseCharacterDefinition:(NSString*)line charDef:(ccBMFontDef*)characterDefinition @@ -370,15 +351,15 @@ - (void)parseCharacterDefinition:(NSString*)line charDef:(ccBMFontDef*)character NSArray *values = [line componentsSeparatedByString:@"="]; NSEnumerator *nse = [values objectEnumerator]; NSString *propertyValue; - + // We need to move past the first entry in the array before we start assigning values [nse nextObject]; - + // Character ID propertyValue = [nse nextObject]; propertyValue = [propertyValue substringToIndex: [propertyValue rangeOfString: @" "].location]; characterDefinition->charID = [propertyValue intValue]; - + // Character x propertyValue = [nse nextObject]; characterDefinition->rect.origin.x = [propertyValue intValue]; @@ -407,22 +388,22 @@ -(void) parseKerningEntry:(NSString*) line NSArray *values = [line componentsSeparatedByString:@"="]; NSEnumerator *nse = [values objectEnumerator]; NSString *propertyValue; - + // We need to move past the first entry in the array before we start assigning values [nse nextObject]; - + // first propertyValue = [nse nextObject]; int first = [propertyValue intValue]; - + // second propertyValue = [nse nextObject]; int second = [propertyValue intValue]; - + // second propertyValue = [nse nextObject]; int amount = [propertyValue intValue]; - + tKerningHashElement *element = calloc( sizeof( *element ), 1 ); element->amount = amount; element->key = (first<<16) | (second&0xffff); @@ -498,25 +479,25 @@ -(id) initWithString:(NSString*)theString fntFile:(NSString*)fntFile width:(floa NSAssert( (theString && fntFile) || (theString==nil && fntFile==nil), @"Invalid params for CCLabelBMFont"); CCTexture2D *texture = nil; - + if( fntFile ) { CCBMFontConfiguration *newConf = FNTConfigLoadFile(fntFile); NSAssert( newConf, @"CCLabelBMFont: Impossible to create font. Please check file: '%@'", fntFile ); - + configuration_ = [newConf retain]; - + fntFile_ = [fntFile retain]; - + texture = [[CCTextureCache sharedTextureCache] addImage:configuration_.atlasName]; - + } else texture = [[[CCTexture2D alloc] init] autorelease]; - - + + if( (self=[super initWithTexture:texture capacity:[theString length]]) ) { width_ = width; alignment_ = alignment; - + opacity_ = 255; color_ = ccWHITE; @@ -525,12 +506,12 @@ -(id) initWithString:(NSString*)theString fntFile:(NSString*)fntFile width:(floa opacityModifyRGB_ = [[textureAtlas_ texture] hasPremultipliedAlpha]; anchorPoint_ = ccp(0.5f, 0.5f); - + imageOffset_ = offset; - + [self setString:theString updateLabel:YES]; } - + return self; } @@ -540,7 +521,7 @@ -(void) dealloc [initialString_ release]; [configuration_ release]; [fntFile_ release]; - + [super dealloc]; } @@ -693,14 +674,14 @@ -(int) kerningAmountForFirst:(unichar)first second:(unichar)second { int ret = 0; unsigned int key = (first<<16) | (second & 0xffff); - + if( configuration_->kerningDictionary_ ) { tKerningHashElement *element = NULL; HASH_FIND_INT(configuration_->kerningDictionary_, &key, element); if(element) ret = element->amount; } - + return ret; } @@ -710,18 +691,18 @@ -(void) createFontChars NSInteger nextFontPositionY = 0; unichar prev = -1; NSInteger kerningAmount = 0; - + CGSize tmpSize = CGSizeZero; - + NSInteger longestLine = 0; NSUInteger totalHeight = 0; - + NSUInteger quantityOfLines = 1; - + NSUInteger stringLen = [string_ length]; if( ! stringLen ) return; - + // quantity of lines NEEDS to be calculated before parsing the lines, // since the Y position needs to be calcualted before hand for(NSUInteger i=0; i < stringLen-1;i++) { @@ -729,21 +710,21 @@ -(void) createFontChars if( c=='\n') quantityOfLines++; } - + totalHeight = configuration_->commonHeight_ * quantityOfLines; nextFontPositionY = -(configuration_->commonHeight_ - configuration_->commonHeight_*quantityOfLines); - + for(NSUInteger i = 0; icommonHeight_; continue; } - + kerningAmount = [self kerningAmountForFirst:prev second:c]; - + tFontDefHashElement *element = NULL; @@ -751,17 +732,17 @@ -(void) createFontChars NSUInteger key = (NSUInteger)c; HASH_FIND_INT(configuration_->fontDefDictionary_ , &key, element); NSAssert(element, @"FontDefinition could not be found!"); - + ccBMFontDef fontDef = element->fontDef; - + CGRect rect = fontDef.rect; rect = CC_RECT_PIXELS_TO_POINTS(rect); rect.origin.x += imageOffset_.x; rect.origin.y += imageOffset_.y; - + CCSprite *fontChar; - + fontChar = (CCSprite*) [self getChildByTag:i]; if( ! fontChar ) { fontChar = [[CCSprite alloc] initWithTexture:textureAtlas_.texture rect:rect]; @@ -771,12 +752,12 @@ -(void) createFontChars else { // reusing fonts [fontChar setTextureRect:rect rotated:NO untrimmedSize:rect.size]; - + // restore to default in case they were modified fontChar.visible = YES; fontChar.opacity = 255; } - + // See issue 1343. cast( signed short + unsigned integer ) == unsigned integer (sign is lost!) NSInteger yOffset = configuration_->commonHeight_ - fontDef.yOffset; CGPoint fontPos = ccp( (CGFloat)nextFontPositionX + fontDef.xOffset + fontDef.rect.size.width*0.5f + kerningAmount, @@ -786,24 +767,24 @@ -(void) createFontChars // update kerning nextFontPositionX += fontDef.xAdvance + kerningAmount; prev = c; - + // Apply label properties [fontChar setOpacityModifyRGB:opacityModifyRGB_]; // Color MUST be set before opacity, since opacity might change color if OpacityModifyRGB is on [fontChar setColor:color_]; - + // only apply opacity if it is different than 255 ) // to prevent modifying the color too (issue #610) if( opacity_ != 255 ) [fontChar setOpacity: opacity_]; - + if (longestLine < nextFontPositionX) longestLine = nextFontPositionX; } - + tmpSize.width = longestLine; tmpSize.height = totalHeight; - + [self setContentSize:CC_SIZE_PIXELS_TO_POINTS(tmpSize)]; } @@ -848,7 +829,7 @@ - (void) setString:(NSString*) newString updateLabel:(BOOL)update -(void) setColor:(ccColor3B)color { color_ = color; - + CCSprite *child; CCARRAY_FOREACH(children_, child) [child setColor:color_]; @@ -857,7 +838,7 @@ -(void) setColor:(ccColor3B)color -(void) setOpacity:(GLubyte)opacity { opacity_ = opacity; - + id child; CCARRAY_FOREACH(children_, child) [child setOpacity:opacity_]; @@ -865,7 +846,7 @@ -(void) setOpacity:(GLubyte)opacity -(void) setOpacityModifyRGB:(BOOL)modify { opacityModifyRGB_ = modify; - + id child; CCARRAY_FOREACH(children_, child) [child setOpacityModifyRGB:modify]; @@ -910,7 +891,7 @@ - (void) setFntFile:(NSString*) fntFile [configuration_ release]; configuration_ = [newConf retain]; - + [self setTexture:[[CCTextureCache sharedTextureCache] addImage:configuration_.atlasName]]; [self createFontChars]; } @@ -926,7 +907,7 @@ - (NSString*) fntFile -(void) draw { [super draw]; - + CGSize s = [self contentSize]; CGPoint vertices[4]={ ccp(0,0),ccp(s.width,0),