// // main.m // charmap // // 20-Apr-09 // Added colour support. User may specify optional parameter to force the generated charmap to // be a particular colour. This allows the use of colour in cocos2D LabelAtlas classes - Dave // // 21-Apr-09 // Added code to wrap the charmap over multiple rows to avoid exceeding the 1024 pixel width limit // on textures. // // #import #import #include #include // parse a hex colour representation into R, G and B components BOOL parseColour( char *string, CGFloat *r, CGFloat *g, CGFloat *b ) { BOOL valid = NO; if( strlen( string) == 6 ) { unsigned int rgb = 0; for( int i=0; i<6; i++ ) { char c = tolower(string[i]); if( ishexnumber(c) ) { rgb *=16; rgb += ( c<= '9')?(c-'0'):(c-'a'+10); } else break; } *r = ( ( rgb & 0x00FF0000 ) >> 16 ); *g = ( ( rgb & 0x0000FF00 ) >> 8 ); *b = ( rgb & 0x000000FF ); valid = YES; } return valid; } int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; [NSApplication sharedApplication]; if (argc < 5) { printf("Proper input: charmap .-9 Arial 15.0 9\ncharmap char-range font-name font-size character-width \n"); [pool drain]; return 1; } NSString *arg1 = [NSString stringWithCString:argv[1] encoding:NSASCIIStringEncoding]; if (!arg1 || [arg1 length] < 3) { printf("Bad char input. Proper input: charmap .-9 Arial 15.0 9\ncharmap char-range font-name font-size character-width \n"); [pool drain]; return 1; } char c1 = [arg1 characterAtIndex:0]; char c2 = [arg1 characterAtIndex:2]; if (c2 < c1) { printf("Bad input: second char must be greater than first char.\n"); [pool drain]; return 1; } NSString *fontName = [NSString stringWithCString:argv[2] encoding:NSASCIIStringEncoding]; float fontSize = [[NSString stringWithCString:argv[3] encoding:NSASCIIStringEncoding] floatValue]; NSFont *font = [NSFont fontWithName:fontName size:fontSize]; if (!font) { printf("Invalid font.\n"); [pool drain]; return 1; } NSView *view = [[NSView alloc] initWithFrame:NSZeroRect]; float glyphWidth = [[NSString stringWithCString:argv[4] encoding:NSASCIIStringEncoding] floatValue]; float glyphHeight = ceil([font ascender]) - floor([font descender]) + 5; // Two optional parameters now, handle them both NSString *outfile = @"charmap.png"; float r,g,b; r = 0.0f; g=0.0f;b=0.0f; if( argc >5 ) { if( argc == 7 ) { // Both colour and filename are present. Parse them outfile = [NSString stringWithCString:argv[5] encoding:NSASCIIStringEncoding]; if( ! parseColour( argv[6], &r, &g, &b ) ) { printf( "Bad colour parameter: Must be in form rrggbb, e.g. 7F7F7F\n" ); [pool drain]; return 1; } } // Only one is present, work out which { // If it's not a colour, assume it's a file name if( ! parseColour( argv[5], &r, &g, &b ) ) outfile = [NSString stringWithCString:argv[5] encoding:NSASCIIStringEncoding]; } } // Work out max chars per line based on width int maxCharsPerRow = 1024 / glyphWidth; int numCharsToGenerate = (c2 - c1) +1; int charsPerRow = numCharsToGenerate; int numRows = 1; // If we have too many, we need to wrap if( maxCharsPerRow < numCharsToGenerate ) { charsPerRow = maxCharsPerRow; numRows = (numCharsToGenerate / maxCharsPerRow) +1; } NSString *charStr = @""; int x=0; int y=numRows-1; for( char c=c1; c<=c2; c++ ) { charStr = [NSString stringWithFormat:@"%c", c]; NSTextField *tf = [[NSTextField alloc] initWithFrame:NSMakeRect(x*glyphWidth, y*glyphHeight, glyphWidth, glyphHeight)]; [tf setFont:font]; [tf setTextColor:[NSColor colorWithDeviceRed:r green:g blue:b alpha:1.0f]]; [tf setAlignment:NSCenterTextAlignment]; [tf setBackgroundColor:[NSColor clearColor]]; [tf setBordered:NO]; [tf setStringValue:charStr]; [view addSubview:tf]; x++; if( x == charsPerRow ) { y--; x=0; } } [view setFrame:NSMakeRect(0, 0, charsPerRow*glyphWidth, numRows*glyphHeight)]; NSWindow *window = [[NSWindow alloc] initWithContentRect:[view frame] styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES]; [window makeKeyAndOrderFront:nil]; [window setContentView:view]; NSBitmapImageRep *bits = [view bitmapImageRepForCachingDisplayInRect:[view frame]]; //[[NSBitmapImageRep alloc] initWithFocusedViewRect:[view frame]]; [view cacheDisplayInRect:[view frame] toBitmapImageRep:bits]; NSData *data = [bits representationUsingType:NSPNGFileType properties:nil]; [data writeToFile:outfile atomically:NO]; [window close]; [pool drain]; return 0; }