2012-07-21 12:23:40 +08:00
|
|
|
/****************************************************************************
|
2014-01-07 11:25:07 +08:00
|
|
|
Copyright (c) 2010-2012 cocos2d-x.org
|
|
|
|
Copyright (c) 2013-2014 Chukong Technologies Inc.
|
2012-07-21 12:23:40 +08:00
|
|
|
|
|
|
|
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
|
|
|
|
2014-09-10 08:17:07 +08:00
|
|
|
#include "platform/CCPlatformConfig.h"
|
2014-01-31 08:51:43 +08:00
|
|
|
#if CC_TARGET_PLATFORM == CC_PLATFORM_MAC
|
|
|
|
|
2014-05-17 05:36:00 +08:00
|
|
|
#include "platform/CCDevice.h"
|
2012-07-21 12:23:40 +08:00
|
|
|
#include <Foundation/Foundation.h>
|
|
|
|
#include <Cocoa/Cocoa.h>
|
|
|
|
#include <string>
|
2014-04-30 08:37:36 +08:00
|
|
|
#include "base/ccTypes.h"
|
2016-06-15 10:43:15 +08:00
|
|
|
#include "platform/apple/CCDevice-apple.h"
|
2012-07-21 12:23:40 +08:00
|
|
|
|
2013-07-18 13:40:32 +08:00
|
|
|
NS_CC_BEGIN
|
|
|
|
|
2016-06-15 10:43:15 +08:00
|
|
|
static NSAttributedString* __attributedStringWithFontSize(NSMutableAttributedString* attributedString, CGFloat fontSize)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
[attributedString beginEditing];
|
|
|
|
|
|
|
|
[attributedString enumerateAttribute:NSFontAttributeName inRange:NSMakeRange(0, attributedString.length) options:0 usingBlock:^(id value, NSRange range, BOOL *stop) {
|
|
|
|
|
|
|
|
NSFont* font = value;
|
|
|
|
font = [[NSFontManager sharedFontManager] convertFont:font toSize:fontSize];
|
|
|
|
|
|
|
|
[attributedString removeAttribute:NSFontAttributeName range:range];
|
|
|
|
[attributedString addAttribute:NSFontAttributeName value:font range:range];
|
|
|
|
}];
|
|
|
|
|
|
|
|
[attributedString endEditing];
|
|
|
|
}
|
|
|
|
|
|
|
|
return [[attributedString copy] autorelease];
|
|
|
|
}
|
|
|
|
|
2014-02-13 21:08:43 +08:00
|
|
|
int Device::getDPI()
|
|
|
|
{
|
2015-08-03 19:42:52 +08:00
|
|
|
NSScreen *screen = [NSScreen mainScreen];
|
|
|
|
NSDictionary *description = [screen deviceDescription];
|
|
|
|
NSSize displayPixelSize = [[description objectForKey:NSDeviceSize] sizeValue];
|
2015-08-04 11:07:04 +08:00
|
|
|
CGSize displayPhysicalSize = CGDisplayScreenSize([[description objectForKey:@"NSScreenNumber"] unsignedIntValue]);
|
2015-08-14 21:17:51 +08:00
|
|
|
|
2015-08-03 19:42:52 +08:00
|
|
|
return ((displayPixelSize.width / displayPhysicalSize.width) * 25.4f);
|
2014-02-13 21:08:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void Device::setAccelerometerEnabled(bool isEnabled)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void Device::setAccelerometerInterval(float interval)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2012-07-21 12:23:40 +08:00
|
|
|
typedef struct
|
|
|
|
{
|
2013-12-06 16:32:06 +08:00
|
|
|
int height;
|
|
|
|
int width;
|
2015-08-14 21:17:51 +08:00
|
|
|
bool hasAlpha;
|
|
|
|
bool isPremultipliedAlpha;
|
|
|
|
unsigned char* data;
|
2012-07-21 12:23:40 +08:00
|
|
|
} tImageInfo;
|
|
|
|
|
2016-06-15 10:43:15 +08:00
|
|
|
static NSSize _calculateStringSize(NSAttributedString *str, id font, CGSize *constrainSize, bool enableWrap, int overflow)
|
2015-12-25 11:44:11 +08:00
|
|
|
{
|
2015-12-25 17:18:15 +08:00
|
|
|
NSSize textRect = NSZeroSize;
|
2015-12-25 11:44:11 +08:00
|
|
|
textRect.width = constrainSize->width > 0 ? constrainSize->width
|
2016-06-15 10:43:15 +08:00
|
|
|
: CGFLOAT_MAX;
|
2015-12-25 11:44:11 +08:00
|
|
|
textRect.height = constrainSize->height > 0 ? constrainSize->height
|
2016-06-15 10:43:15 +08:00
|
|
|
: CGFLOAT_MAX;
|
|
|
|
|
|
|
|
if (overflow == 1) {
|
|
|
|
if (!enableWrap) {
|
|
|
|
textRect.width = CGFLOAT_MAX;
|
|
|
|
textRect.height = CGFLOAT_MAX;
|
|
|
|
} else {
|
|
|
|
textRect.height = CGFLOAT_MAX;
|
|
|
|
}
|
|
|
|
}
|
2015-12-25 11:44:11 +08:00
|
|
|
|
2015-12-25 17:18:15 +08:00
|
|
|
NSSize dim;
|
2015-12-29 18:31:20 +08:00
|
|
|
#ifdef __MAC_10_11
|
|
|
|
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_11
|
2016-06-15 10:43:15 +08:00
|
|
|
dim = [str boundingRectWithSize:textRect options:(NSStringDrawingOptions)(NSStringDrawingUsesLineFragmentOrigin) context:nil].size;
|
2015-12-29 18:31:20 +08:00
|
|
|
#else
|
2016-06-15 10:43:15 +08:00
|
|
|
dim = [str boundingRectWithSize:textRect options:(NSStringDrawingOptions)(NSStringDrawingUsesLineFragmentOrigin)].size;
|
2015-12-29 18:31:20 +08:00
|
|
|
#endif
|
|
|
|
#else
|
2016-06-15 10:43:15 +08:00
|
|
|
dim = [str boundingRectWithSize:textRect options:(NSStringDrawingOptions)(NSStringDrawingUsesLineFragmentOrigin)].size;
|
2015-12-29 18:31:20 +08:00
|
|
|
#endif
|
2015-12-25 11:44:11 +08:00
|
|
|
|
2016-06-15 10:43:15 +08:00
|
|
|
|
2015-12-25 11:44:11 +08:00
|
|
|
dim.width = ceilf(dim.width);
|
|
|
|
dim.height = ceilf(dim.height);
|
2015-12-25 17:18:15 +08:00
|
|
|
|
2015-12-25 11:44:11 +08:00
|
|
|
return dim;
|
|
|
|
}
|
|
|
|
|
2016-06-15 10:43:15 +08:00
|
|
|
static NSSize _calculateRealSizeForString(NSAttributedString **str, id font, NSSize constrainSize, bool enableWrap)
|
|
|
|
{
|
|
|
|
CGRect actualSize = CGRectMake(0, 0, constrainSize.width + 1, constrainSize.height + 1);
|
|
|
|
int fontSize = [font pointSize];
|
|
|
|
fontSize = fontSize + 1;
|
|
|
|
|
|
|
|
if (!enableWrap) {
|
|
|
|
while (actualSize.size.width > constrainSize.width ||
|
|
|
|
actualSize.size.height > constrainSize.height) {
|
|
|
|
fontSize = fontSize - 1;
|
|
|
|
|
|
|
|
NSMutableAttributedString *mutableString = [[*str mutableCopy] autorelease];
|
|
|
|
*str = __attributedStringWithFontSize(mutableString, fontSize);
|
|
|
|
|
|
|
|
CGSize fitSize = [*str boundingRectWithSize:CGSizeMake( CGFLOAT_MAX, CGFLOAT_MAX)
|
|
|
|
options:NSStringDrawingUsesLineFragmentOrigin
|
|
|
|
context:nil].size;
|
|
|
|
|
|
|
|
if(fitSize.width == 0 || fitSize.height == 0) continue;
|
|
|
|
actualSize.size = fitSize;
|
|
|
|
|
|
|
|
if (constrainSize.width <= 0) {
|
|
|
|
constrainSize.width = fitSize.width;
|
|
|
|
}
|
|
|
|
if (constrainSize.height <= 0){
|
|
|
|
constrainSize.height = fitSize.height;
|
|
|
|
}
|
|
|
|
if(fontSize <= 0){
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
while (actualSize.size.height > constrainSize.height
|
|
|
|
||actualSize.size.width > constrainSize.width) {
|
|
|
|
fontSize = fontSize - 1;
|
|
|
|
|
|
|
|
NSMutableAttributedString *mutableString = [[*str mutableCopy] autorelease];
|
|
|
|
*str = __attributedStringWithFontSize(mutableString, fontSize);
|
|
|
|
|
|
|
|
CGSize fitSize = [*str boundingRectWithSize:CGSizeMake( constrainSize.width, CGFLOAT_MAX)
|
|
|
|
options:NSStringDrawingUsesLineFragmentOrigin
|
|
|
|
context:nil].size;
|
|
|
|
|
|
|
|
if(fitSize.width == 0 || fitSize.height == 0) continue;
|
|
|
|
actualSize.size = fitSize;
|
|
|
|
|
|
|
|
if (constrainSize.width <= 0) {
|
|
|
|
constrainSize.width = fitSize.width;
|
|
|
|
}
|
|
|
|
if (constrainSize.height <= 0){
|
|
|
|
constrainSize.height = fitSize.height;
|
|
|
|
}
|
|
|
|
if(fontSize <= 0){
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
return CGSizeMake(actualSize.size.width, actualSize.size.height);
|
|
|
|
}
|
|
|
|
|
|
|
|
static NSFont* _createSystemFont(const char* fontName, int size)
|
|
|
|
{
|
|
|
|
NSString * fntName = [NSString stringWithUTF8String:fontName];
|
|
|
|
fntName = [[fntName lastPathComponent] stringByDeletingPathExtension];
|
|
|
|
|
|
|
|
// font
|
|
|
|
NSFont *font = [[NSFontManager sharedFontManager]
|
|
|
|
fontWithFamily:fntName
|
|
|
|
traits:NSUnboldFontMask | NSUnitalicFontMask
|
|
|
|
weight:0
|
|
|
|
size:size];
|
|
|
|
|
|
|
|
if (font == nil) {
|
|
|
|
font = [[NSFontManager sharedFontManager]
|
|
|
|
fontWithFamily:@"Arial"
|
|
|
|
traits:NSUnboldFontMask | NSUnitalicFontMask
|
|
|
|
weight:0
|
|
|
|
size:size];
|
|
|
|
}
|
|
|
|
return font;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static CGFloat _calculateTextDrawStartHeight(cocos2d::Device::TextAlign align, CGSize realDimensions, CGSize dimensions)
|
|
|
|
{
|
|
|
|
float startH = 0;
|
|
|
|
// vertical alignment
|
|
|
|
unsigned int vAlignment = ((int)align >> 4) & 0x0F;
|
|
|
|
switch (vAlignment) {
|
|
|
|
//bottom
|
|
|
|
case 1:startH = dimensions.height - realDimensions.height;break;
|
|
|
|
//top
|
|
|
|
case 2:startH = 0;break;
|
|
|
|
//center
|
|
|
|
case 3: startH = (dimensions.height - realDimensions.height) / 2;break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return startH;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool _initWithString(const char * text, Device::TextAlign align, const char * fontName, int size, tImageInfo* info, const Color3B* fontColor, int fontAlpha, bool enableWrap, int overflow)
|
2012-07-21 12:23:40 +08:00
|
|
|
{
|
2013-12-18 17:47:20 +08:00
|
|
|
bool ret = false;
|
2014-02-13 21:08:43 +08:00
|
|
|
|
2015-12-25 11:44:11 +08:00
|
|
|
CCASSERT(text, "Invalid text");
|
|
|
|
CCASSERT(info, "Invalid info");
|
2015-08-14 21:17:51 +08:00
|
|
|
|
|
|
|
do {
|
|
|
|
NSString * string = [NSString stringWithUTF8String:text];
|
2016-07-09 07:59:44 +08:00
|
|
|
CC_BREAK_IF(!string);
|
2016-06-15 10:43:15 +08:00
|
|
|
|
|
|
|
id font = _createSystemFont(fontName, size);
|
2015-08-14 21:17:51 +08:00
|
|
|
CC_BREAK_IF(!font);
|
|
|
|
|
|
|
|
// color
|
|
|
|
NSColor* foregroundColor;
|
2015-01-20 16:04:14 +08:00
|
|
|
if (fontColor) {
|
2016-06-15 10:43:15 +08:00
|
|
|
foregroundColor = [NSColor colorWithDeviceRed:fontColor->r/255.0
|
|
|
|
green:fontColor->g/255.0
|
|
|
|
blue:fontColor->b/255.0
|
|
|
|
alpha:fontAlpha/255.0];
|
2015-08-14 21:17:51 +08:00
|
|
|
} else {
|
|
|
|
foregroundColor = [NSColor whiteColor];
|
|
|
|
}
|
|
|
|
|
2015-12-25 11:44:11 +08:00
|
|
|
// alignment
|
2016-06-15 10:43:15 +08:00
|
|
|
NSTextAlignment textAlign = FontUtils::_calculateTextAlignment(align);
|
2014-02-13 21:08:43 +08:00
|
|
|
|
2016-06-15 10:43:15 +08:00
|
|
|
NSMutableParagraphStyle *paragraphStyle = FontUtils::_calculateParagraphStyle(enableWrap, overflow);
|
2015-08-14 21:17:51 +08:00
|
|
|
[paragraphStyle setAlignment:textAlign];
|
|
|
|
|
|
|
|
// attribute
|
|
|
|
NSDictionary* tokenAttributesDict = [NSDictionary dictionaryWithObjectsAndKeys:
|
|
|
|
foregroundColor,NSForegroundColorAttributeName,
|
|
|
|
font, NSFontAttributeName,
|
|
|
|
paragraphStyle, NSParagraphStyleAttributeName, nil];
|
|
|
|
NSAttributedString *stringWithAttributes =[[[NSAttributedString alloc] initWithString:string
|
2014-02-13 21:08:43 +08:00
|
|
|
attributes:tokenAttributesDict] autorelease];
|
|
|
|
|
2015-12-25 11:44:11 +08:00
|
|
|
CGSize dimensions = CGSizeMake(info->width, info->height);
|
2016-06-15 10:43:15 +08:00
|
|
|
|
|
|
|
NSSize realDimensions;
|
|
|
|
|
|
|
|
if (overflow == 2) {
|
|
|
|
realDimensions = _calculateRealSizeForString(&stringWithAttributes, font, dimensions, enableWrap);
|
|
|
|
} else {
|
|
|
|
realDimensions = _calculateStringSize(stringWithAttributes, font, &dimensions, enableWrap, overflow);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-08-14 21:17:51 +08:00
|
|
|
// Mac crashes if the width or height is 0
|
|
|
|
CC_BREAK_IF(realDimensions.width <= 0 || realDimensions.height <= 0);
|
2014-02-13 21:08:43 +08:00
|
|
|
|
2016-06-15 10:43:15 +08:00
|
|
|
|
2015-07-29 16:11:27 +08:00
|
|
|
if(dimensions.width <= 0.f) {
|
|
|
|
dimensions.width = realDimensions.width;
|
|
|
|
}
|
|
|
|
if (dimensions.height <= 0.f) {
|
|
|
|
dimensions.height = realDimensions.height;
|
|
|
|
}
|
2016-06-15 10:43:15 +08:00
|
|
|
|
2014-02-13 21:08:43 +08:00
|
|
|
|
2015-08-14 21:17:51 +08:00
|
|
|
//Alignment
|
2016-06-15 10:43:15 +08:00
|
|
|
CGFloat xPadding = FontUtils::_calculateTextDrawStartWidth(align, realDimensions, dimensions);
|
2014-02-13 21:08:43 +08:00
|
|
|
|
2016-06-15 10:43:15 +08:00
|
|
|
CGFloat yPadding = _calculateTextDrawStartHeight(align, realDimensions, dimensions);
|
2013-02-27 11:10:42 +08:00
|
|
|
|
2015-12-25 11:44:11 +08:00
|
|
|
NSInteger POTWide = dimensions.width;
|
|
|
|
NSInteger POTHigh = dimensions.height;
|
2016-06-15 10:43:15 +08:00
|
|
|
NSRect textRect = NSMakeRect(xPadding, POTHigh - dimensions.height + yPadding,
|
|
|
|
realDimensions.width, realDimensions.height);
|
|
|
|
|
|
|
|
|
2015-08-14 21:17:51 +08:00
|
|
|
[[NSGraphicsContext currentContext] setShouldAntialias:NO];
|
|
|
|
|
|
|
|
NSImage *image = [[NSImage alloc] initWithSize:NSMakeSize(POTWide, POTHigh)];
|
|
|
|
[image lockFocus];
|
2015-12-25 11:44:11 +08:00
|
|
|
// patch for mac retina display and lableTTF
|
2013-02-27 11:10:42 +08:00
|
|
|
[[NSAffineTransform transform] set];
|
2015-08-14 21:17:51 +08:00
|
|
|
[stringWithAttributes drawInRect:textRect];
|
|
|
|
NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithFocusedViewRect:NSMakeRect (0.0f, 0.0f, POTWide, POTHigh)];
|
|
|
|
[image unlockFocus];
|
|
|
|
|
2015-12-25 11:44:11 +08:00
|
|
|
auto data = (unsigned char*) [bitmap bitmapData]; //Use the same buffer to improve the performance.
|
2015-08-14 21:17:51 +08:00
|
|
|
|
2015-12-25 11:44:11 +08:00
|
|
|
NSUInteger textureSize = POTWide * POTHigh * 4;
|
|
|
|
auto dataNew = (unsigned char*)malloc(sizeof(unsigned char) * textureSize);
|
2015-08-14 21:17:51 +08:00
|
|
|
if (dataNew) {
|
|
|
|
memcpy(dataNew, data, textureSize);
|
|
|
|
// output params
|
|
|
|
info->width = static_cast<int>(POTWide);
|
|
|
|
info->height = static_cast<int>(POTHigh);
|
|
|
|
info->data = dataNew;
|
|
|
|
info->hasAlpha = true;
|
|
|
|
info->isPremultipliedAlpha = true;
|
|
|
|
ret = true;
|
|
|
|
}
|
|
|
|
[bitmap release];
|
|
|
|
[image release];
|
|
|
|
} while (0);
|
2013-12-18 17:47:20 +08:00
|
|
|
return ret;
|
2012-07-21 12:23:40 +08:00
|
|
|
}
|
|
|
|
|
2014-05-06 10:36:55 +08:00
|
|
|
Data Device::getTextureDataForText(const char * text, const FontDefinition& textDefinition, TextAlign align, int &width, int &height, bool& hasPremultipliedAlpha)
|
2012-07-21 12:23:40 +08:00
|
|
|
{
|
2014-02-13 21:08:43 +08:00
|
|
|
Data ret;
|
|
|
|
do {
|
|
|
|
tImageInfo info = {0};
|
|
|
|
info.width = textDefinition._dimensions.width;
|
|
|
|
info.height = textDefinition._dimensions.height;
|
|
|
|
|
2016-06-15 10:43:15 +08:00
|
|
|
if (! _initWithString(text, align, textDefinition._fontName.c_str(), textDefinition._fontSize, &info, &textDefinition._fontFillColor, textDefinition._fontAlpha, textDefinition._enableWrap, textDefinition._overflow))
|
2014-02-13 21:08:43 +08:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
height = (short)info.height;
|
2014-02-14 09:41:06 +08:00
|
|
|
width = (short)info.width;
|
2014-02-13 21:08:43 +08:00
|
|
|
ret.fastSet(info.data,width * height * 4);
|
2014-05-06 11:22:23 +08:00
|
|
|
hasPremultipliedAlpha = true;
|
2014-02-13 21:08:43 +08:00
|
|
|
} while (0);
|
|
|
|
|
|
|
|
return ret;
|
2012-07-21 12:23:40 +08:00
|
|
|
}
|
2014-08-18 20:41:12 +08:00
|
|
|
|
|
|
|
void Device::setKeepScreenOn(bool value)
|
|
|
|
{
|
2015-06-25 17:36:57 +08:00
|
|
|
CC_UNUSED_PARAM(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Device::vibrate(float duration)
|
|
|
|
{
|
|
|
|
CC_UNUSED_PARAM(duration);
|
2014-08-18 20:41:12 +08:00
|
|
|
}
|
|
|
|
|
2012-09-05 16:15:09 +08:00
|
|
|
NS_CC_END
|
2012-07-21 12:23:40 +08:00
|
|
|
|
2016-06-15 10:43:15 +08:00
|
|
|
#endif // CC_TARGET_PLATFORM == CC_PLATFORM_MAC
|