static bool _initWithString(const char * pText, cocos2d::CCImage::ETextAlign eAlign, const char * pFontName, int nSize, tImageInfo* pInfo)
{
bool bRet = false;
do
{
CC_BREAK_IF(! pText || ! pInfo);
NSMutableDictionary *textAttributes = [NSMutableDictionary dictionary];
bool osVersionSince7 = [[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0;
NSString * str = [NSString stringWithUTF8String:pText];
NSString * fntName = [NSString stringWithUTF8String:pFontName];
CGSize dim, constrainSize;
constrainSize.width = pInfo->width;
constrainSize.height = pInfo->height;
// On iOS custom fonts must be listed beforehand in the App info.plist (in order to be usable) and referenced only the by the font family name itself when
// calling [UIFont fontWithName]. Therefore even if the developer adds 'SomeFont.ttf' or 'fonts/SomeFont.ttf' to the App .plist, the font must
// be referenced as 'SomeFont' when calling [UIFont fontWithName]. Hence we strip out the folder path components and the extension here in order to get just
// the font family name itself. This stripping step is required especially for references to user fonts stored in CCB files; CCB files appear to store
// the '.ttf' extensions when referring to custom fonts.
fntName = [[fntName lastPathComponent] stringByDeletingPathExtension];
// create the font
id font = [UIFont fontWithName:fntName size:nSize];
if (font)
{
dim = _calculateStringSize(str, font, &constrainSize);
}
else
{
if (!font)
{
font = [UIFont systemFontOfSize:nSize];
}
if (font)
{
dim = _calculateStringSize(str, font, &constrainSize);
}
}
CC_BREAK_IF(! font);
[textAttributes setObject:font forKey:NSFontAttributeName];
// compute start point
int startH = 0;
if (constrainSize.height > dim.height)
{
// vertical alignment
unsigned int vAlignment = (eAlign >> 4) & 0x0F;
if (vAlignment == ALIGN_TOP)
{
startH = 0;
}
else if (vAlignment == ALIGN_CENTER)
{
startH = (constrainSize.height - dim.height) / 2;
}
else
{
startH = constrainSize.height - dim.height;
}
}
// adjust text rect
if (constrainSize.width > 0 && constrainSize.width > dim.width)
{
dim.width = constrainSize.width;
}
if (constrainSize.height > 0 && constrainSize.height > dim.height)
{
dim.height = constrainSize.height;
}
// compute the padding needed by shadow and stroke
float shadowStrokePaddingX = 0.0f;
float shadowStrokePaddingY = 0.0f;
if ( pInfo->hasStroke )
{
shadowStrokePaddingX = ceilf(pInfo->strokeSize);
shadowStrokePaddingY = ceilf(pInfo->strokeSize);
}
if ( pInfo->hasShadow )
{
shadowStrokePaddingX = std::max(shadowStrokePaddingX, (float)abs(pInfo->shadowOffset.width));
shadowStrokePaddingY = std::max(shadowStrokePaddingY, (float)abs(pInfo->shadowOffset.height));
}
// add the padding (this could be 0 if no shadow and no stroke)
dim.width += shadowStrokePaddingX;
dim.height += shadowStrokePaddingY;
unsigned char* data = new unsigned char[(int)(dim.width * dim.height * 4)];
memset(data, 0, (int)(dim.width * dim.height * 4));
// draw text
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(data,
dim.width,
dim.height,
8,
(int)(dim.width) * 4,
colorSpace,
kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);
if (!context)
{
delete[] data;
break;
}
// text color
CGContextSetRGBFillColor(context, pInfo->tintColorR, pInfo->tintColorG, pInfo->tintColorB, 1);
if (osVersionSince7)
{
[textAttributes setObject:[UIColor colorWithRed:pInfo->tintColorR green:pInfo->tintColorG blue:pInfo->tintColorB alpha:1] forKey:NSForegroundColorAttributeName];
}
// move Y rendering to the top of the image
CGContextTranslateCTM(context, 0.0f, (dim.height - shadowStrokePaddingY) );
CGContextScaleCTM(context, 1.0f, -1.0f); //NOTE: NSString draws in UIKit referential i.e. renders upside-down compared to CGBitmapContext referential
// store the current context
UIGraphicsPushContext(context);
// measure text size with specified font and determine the rectangle to draw text in
unsigned uHoriFlag = eAlign & 0x0f;
UITextAlignment align = (UITextAlignment)((2 == uHoriFlag) ? UITextAlignmentRight
: (3 == uHoriFlag) ? UITextAlignmentCenter
: UITextAlignmentLeft);
// take care of stroke if needed
if ( pInfo->hasStroke )
{
if (osVersionSince7)
{
[textAttributes setObject:[UIColor colorWithRed:pInfo->strokeColorR green:pInfo->strokeColorG blue:pInfo->strokeColorB alpha:1] forKey:NSStrokeColorAttributeName];
[textAttributes setObject:[NSNumber numberWithFloat:-pInfo->strokeSize*100.0f/nSize] forKey:NSStrokeWidthAttributeName];
}
else
{
CGContextSetTextDrawingMode(context, kCGTextFillStroke);
CGContextSetRGBStrokeColor(context, pInfo->strokeColorR, pInfo->strokeColorG, pInfo->strokeColorB, 1);
CGContextSetLineWidth(context, pInfo->strokeSize);
}
}
// take care of shadow if needed
if ( pInfo->hasShadow )
{
if (osVersionSince7)
{
NSShadow* shadow = [[NSShadow new] autorelease];
shadow.shadowOffset = pInfo->shadowOffset;
shadow.shadowBlurRadius = pInfo->shadowBlur;
[textAttributes setObject:shadow forKey:NSShadowAttributeName];
}
else
{
CGSize offset;
offset.height = pInfo->shadowOffset.height;
offset.width = pInfo->shadowOffset.width;
CGContextSetShadow(context, offset, pInfo->shadowBlur);
}
}
// normal fonts
//if( [font isKindOfClass:[UIFont class] ] )
//{
// [str drawInRect:CGRectMake(0, startH, dim.width, dim.height) withFont:font lineBreakMode:(UILineBreakMode)UILineBreakModeWordWrap alignment:align];
//}
//else // ZFont class
//{
// [FontLabelStringDrawingHelper drawInRect:str rect:CGRectMake(0, startH, dim.width, dim.height) withZFont:font lineBreakMode:(UILineBreakMode)UILineBreakModeWordWrap
alignment:align];
//}
// compute the rect used for rendering the text
// based on wether shadows or stroke are enabled
float textOriginX = 0.0;
float textOrigingY = 0.0;
float textWidth = dim.width - shadowStrokePaddingX;
float textHeight = dim.height - shadowStrokePaddingY;
if ( pInfo->shadowOffset.width < 0 )
{
textOriginX = shadowStrokePaddingX;
}
else
{
textOriginX = 0.0;
}
if (pInfo->shadowOffset.height > 0)
{
textOrigingY = startH;
}
else
{
textOrigingY = startH - shadowStrokePaddingY;
}
// actually draw the text in the context
if (osVersionSince7)
{
/// Make a copy of the default paragraph style
NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
paragraphStyle.alignment = (NSTextAlignment)align;
[textAttributes setObject:paragraphStyle forKey:NSParagraphStyleAttributeName];
[str drawInRect:CGRectMake(textOriginX, textOrigingY, textWidth, textHeight) withAttributes:textAttributes];
[paragraphStyle release];
}
else
{
[str drawInRect:CGRectMake(textOriginX, textOrigingY, textWidth, textHeight) withFont:font lineBreakMode:NSLineBreakByWordWrapping alignment:(NSTextAlignment)align];
}
// pop the context
UIGraphicsPopContext();
// release the context
CGContextRelease(context);
// output params
pInfo->data = data;
pInfo->hasAlpha = true;
pInfo->isPremultipliedAlpha = true;
pInfo->bitsPerComponent = 8;
pInfo->width = dim.width;
pInfo->height = dim.height;
bRet = true;
} while (0);
return bRet;
}
简单说下一些注意点:
NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
paragraphStyle.alignment = (NSTextAlignment)align;
[textAttributes setObject:paragraphStyle forKey:NSParagraphStyleAttributeName];