2012-07-21 12:23:40 +08:00
|
|
|
/****************************************************************************
|
|
|
|
Copyright (c) 2010 cocos2d-x.org
|
|
|
|
|
|
|
|
http://www.cocos2d-x.org
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
|
|
in the Software without restriction, including without limitation the rights
|
|
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
|
|
all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
THE SOFTWARE.
|
|
|
|
****************************************************************************/
|
2013-07-17 17:12:04 +08:00
|
|
|
|
|
|
|
#include "CCImageCommon_cpp.h"
|
2012-07-21 12:23:40 +08:00
|
|
|
#include <Foundation/Foundation.h>
|
|
|
|
#include <Cocoa/Cocoa.h>
|
|
|
|
#include "CCDirector.h"
|
|
|
|
#include "ccMacros.h"
|
|
|
|
#include "CCImage.h"
|
|
|
|
#include "CCFileUtils.h"
|
|
|
|
#include "CCTexture2D.h"
|
|
|
|
#include <string>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
2013-07-18 13:40:32 +08:00
|
|
|
NS_CC_BEGIN
|
|
|
|
|
2012-07-21 12:23:40 +08:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
unsigned int height;
|
|
|
|
unsigned int width;
|
|
|
|
bool hasAlpha;
|
|
|
|
bool isPremultipliedAlpha;
|
|
|
|
unsigned char* data;
|
|
|
|
} tImageInfo;
|
|
|
|
|
2013-07-19 15:37:54 +08:00
|
|
|
static bool _initWithString(const char * pText, cocos2d::Image::TextAlign eAlign, const char * pFontName, int nSize, tImageInfo* pInfo, cocos2d::Color3B* pStrokeColor)
|
2012-07-21 12:23:40 +08:00
|
|
|
{
|
|
|
|
bool bRet = false;
|
|
|
|
|
2012-09-04 11:16:59 +08:00
|
|
|
CCAssert(pText, "Invalid pText");
|
|
|
|
CCAssert(pInfo, "Invalid pInfo");
|
2012-07-21 12:23:40 +08:00
|
|
|
|
|
|
|
do {
|
|
|
|
NSString * string = [NSString stringWithUTF8String:pText];
|
|
|
|
|
|
|
|
// font
|
|
|
|
NSFont *font = [[NSFontManager sharedFontManager]
|
|
|
|
fontWithFamily:[NSString stringWithUTF8String:pFontName]
|
|
|
|
traits:NSUnboldFontMask | NSUnitalicFontMask
|
|
|
|
weight:0
|
|
|
|
size:nSize];
|
|
|
|
|
|
|
|
if (font == nil) {
|
|
|
|
font = [[NSFontManager sharedFontManager]
|
|
|
|
fontWithFamily:@"Arial"
|
|
|
|
traits:NSUnboldFontMask | NSUnitalicFontMask
|
|
|
|
weight:0
|
|
|
|
size:nSize];
|
|
|
|
}
|
|
|
|
CC_BREAK_IF(!font);
|
|
|
|
|
|
|
|
// color
|
|
|
|
NSColor* foregroundColor;
|
|
|
|
if (pStrokeColor) {
|
|
|
|
foregroundColor = [NSColor colorWithDeviceRed:pStrokeColor->r/255.0 green:pStrokeColor->g/255.0 blue:pStrokeColor->b/255.0 alpha:1];
|
|
|
|
} else {
|
|
|
|
foregroundColor = [NSColor whiteColor];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// alignment, linebreak
|
|
|
|
unsigned uHoriFlag = eAlign & 0x0f;
|
2013-06-12 05:59:40 +08:00
|
|
|
unsigned uVertFlag = (eAlign >> 4) & 0x0f;
|
2012-07-21 12:23:40 +08:00
|
|
|
NSTextAlignment align = (2 == uHoriFlag) ? NSRightTextAlignment
|
|
|
|
: (3 == uHoriFlag) ? NSCenterTextAlignment
|
|
|
|
: NSLeftTextAlignment;
|
|
|
|
|
|
|
|
NSMutableParagraphStyle *paragraphStyle = [[[NSMutableParagraphStyle alloc] init] autorelease];
|
|
|
|
[paragraphStyle setParagraphStyle:[NSParagraphStyle defaultParagraphStyle]];
|
|
|
|
[paragraphStyle setLineBreakMode:NSLineBreakByCharWrapping];
|
|
|
|
[paragraphStyle setAlignment:align];
|
|
|
|
|
|
|
|
// attribute
|
|
|
|
NSDictionary* tokenAttributesDict = [NSDictionary dictionaryWithObjectsAndKeys:
|
|
|
|
foregroundColor,NSForegroundColorAttributeName,
|
|
|
|
font, NSFontAttributeName,
|
|
|
|
paragraphStyle, NSParagraphStyleAttributeName, nil];
|
|
|
|
|
|
|
|
// linebreak
|
|
|
|
if (pInfo->width > 0) {
|
|
|
|
if ([string sizeWithAttributes:tokenAttributesDict].width > pInfo->width) {
|
|
|
|
NSMutableString *lineBreak = [[[NSMutableString alloc] init] autorelease];
|
|
|
|
NSUInteger length = [string length];
|
|
|
|
NSRange range = NSMakeRange(0, 1);
|
|
|
|
NSUInteger width = 0;
|
2013-05-29 22:40:19 +08:00
|
|
|
NSUInteger lastBreakLocation = 0;
|
2012-07-21 12:23:40 +08:00
|
|
|
for (NSUInteger i = 0; i < length; i++) {
|
|
|
|
range.location = i;
|
2013-05-29 22:40:19 +08:00
|
|
|
NSString *character = [string substringWithRange:range];
|
2013-05-24 01:30:56 +08:00
|
|
|
[lineBreak appendString:character];
|
2013-05-29 22:40:19 +08:00
|
|
|
if ([@"!?.,-= " rangeOfString:character].location != NSNotFound) { lastBreakLocation = i; }
|
2012-07-21 12:23:40 +08:00
|
|
|
width = [lineBreak sizeWithAttributes:tokenAttributesDict].width;
|
|
|
|
if (width > pInfo->width) {
|
2013-05-24 01:30:56 +08:00
|
|
|
[lineBreak insertString:@"\r\n" atIndex:(lastBreakLocation > 0) ? lastBreakLocation : [lineBreak length] - 1];
|
2012-07-21 12:23:40 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
string = lineBreak;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NSAttributedString *stringWithAttributes =[[[NSAttributedString alloc] initWithString:string
|
|
|
|
attributes:tokenAttributesDict] autorelease];
|
|
|
|
|
|
|
|
NSSize realDimensions = [stringWithAttributes size];
|
|
|
|
// Mac crashes if the width or height is 0
|
|
|
|
CC_BREAK_IF(realDimensions.width <= 0 || realDimensions.height <= 0);
|
|
|
|
|
|
|
|
CGSize dimensions = CGSizeMake(pInfo->width, pInfo->height);
|
|
|
|
|
|
|
|
|
|
|
|
if(dimensions.width <= 0 && dimensions.height <= 0) {
|
|
|
|
dimensions.width = realDimensions.width;
|
|
|
|
dimensions.height = realDimensions.height;
|
|
|
|
} else if (dimensions.height <= 0) {
|
|
|
|
dimensions.height = realDimensions.height;
|
|
|
|
}
|
|
|
|
|
|
|
|
NSUInteger POTWide = (NSUInteger)dimensions.width;
|
|
|
|
NSUInteger POTHigh = (NSUInteger)(MAX(dimensions.height, realDimensions.height));
|
|
|
|
unsigned char* data;
|
|
|
|
//Alignment
|
|
|
|
|
|
|
|
CGFloat xPadding = 0;
|
|
|
|
switch (align) {
|
|
|
|
case NSLeftTextAlignment: xPadding = 0; break;
|
|
|
|
case NSCenterTextAlignment: xPadding = (dimensions.width-realDimensions.width)/2.0f; break;
|
|
|
|
case NSRightTextAlignment: xPadding = dimensions.width-realDimensions.width; break;
|
|
|
|
default: break;
|
|
|
|
}
|
2013-06-12 05:59:40 +08:00
|
|
|
|
|
|
|
// 1: TOP
|
|
|
|
// 2: BOTTOM
|
|
|
|
// 3: CENTER
|
|
|
|
CGFloat yPadding = (1 == uVertFlag || realDimensions.height >= dimensions.height) ? (dimensions.height - realDimensions.height) // align to top
|
|
|
|
: (2 == uVertFlag) ? 0 // align to bottom
|
2012-07-21 12:23:40 +08:00
|
|
|
: (dimensions.height - realDimensions.height) / 2.0f; // align to center
|
|
|
|
|
|
|
|
|
|
|
|
NSRect textRect = NSMakeRect(xPadding, POTHigh - dimensions.height + yPadding, realDimensions.width, realDimensions.height);
|
|
|
|
//Disable antialias
|
|
|
|
|
|
|
|
[[NSGraphicsContext currentContext] setShouldAntialias:NO];
|
|
|
|
|
|
|
|
NSImage *image = [[NSImage alloc] initWithSize:NSMakeSize(POTWide, POTHigh)];
|
2013-02-27 11:10:42 +08:00
|
|
|
|
|
|
|
[image lockFocus];
|
|
|
|
|
|
|
|
// patch for mac retina display and lableTTF
|
|
|
|
[[NSAffineTransform transform] set];
|
2012-07-21 12:23:40 +08:00
|
|
|
|
|
|
|
//[stringWithAttributes drawAtPoint:NSMakePoint(xPadding, offsetY)]; // draw at offset position
|
|
|
|
[stringWithAttributes drawInRect:textRect];
|
|
|
|
//[stringWithAttributes drawInRect:textRect withAttributes:tokenAttributesDict];
|
|
|
|
NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithFocusedViewRect:NSMakeRect (0.0f, 0.0f, POTWide, POTHigh)];
|
|
|
|
[image unlockFocus];
|
|
|
|
|
|
|
|
data = (unsigned char*) [bitmap bitmapData]; //Use the same buffer to improve the performance.
|
|
|
|
|
|
|
|
NSUInteger textureSize = POTWide*POTHigh*4;
|
|
|
|
|
|
|
|
unsigned char* dataNew = new unsigned char[textureSize];
|
2012-08-25 12:39:41 +08:00
|
|
|
if (dataNew) {
|
|
|
|
memcpy(dataNew, data, textureSize);
|
|
|
|
// output params
|
|
|
|
pInfo->width = POTWide;
|
|
|
|
pInfo->height = POTHigh;
|
|
|
|
pInfo->data = dataNew;
|
|
|
|
pInfo->hasAlpha = true;
|
|
|
|
pInfo->isPremultipliedAlpha = true;
|
|
|
|
bRet = true;
|
|
|
|
}
|
2012-07-21 12:23:40 +08:00
|
|
|
[bitmap release];
|
2012-08-25 12:39:41 +08:00
|
|
|
[image release];
|
2012-07-21 12:23:40 +08:00
|
|
|
} while (0);
|
|
|
|
return bRet;
|
|
|
|
}
|
|
|
|
|
2013-06-20 14:13:12 +08:00
|
|
|
bool Image::initWithString(
|
2012-07-21 12:23:40 +08:00
|
|
|
const char * pText,
|
|
|
|
int nWidth,
|
|
|
|
int nHeight,
|
2013-07-19 15:37:54 +08:00
|
|
|
TextAlign eAlignMask,
|
2012-07-21 12:23:40 +08:00
|
|
|
const char * pFontName,
|
|
|
|
int nSize)
|
|
|
|
{
|
|
|
|
tImageInfo info = {0};
|
|
|
|
info.width = nWidth;
|
|
|
|
info.height = nHeight;
|
|
|
|
|
|
|
|
if (! _initWithString(pText, eAlignMask, pFontName, nSize, &info, NULL)) //pStrokeColor))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2013-06-15 14:03:30 +08:00
|
|
|
_height = (short)info.height;
|
|
|
|
_width = (short)info.width;
|
2013-07-25 21:35:00 +08:00
|
|
|
_renderFormat = kTexture2DPixelFormat_RGBA8888;
|
2013-06-15 14:03:30 +08:00
|
|
|
_hasAlpha = info.hasAlpha;
|
|
|
|
_preMulti = info.isPremultipliedAlpha;
|
|
|
|
if (_data) {
|
|
|
|
CC_SAFE_DELETE_ARRAY(_data);
|
2012-07-21 12:23:40 +08:00
|
|
|
}
|
2013-06-15 14:03:30 +08:00
|
|
|
_data = info.data;
|
2012-07-21 12:23:40 +08:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-05 16:15:09 +08:00
|
|
|
NS_CC_END
|
2012-07-21 12:23:40 +08:00
|
|
|
|