修复cocos2dx的Label,WP8下不能换行的问题
注:2014年12月23日有内存/性能优化更新,内容在下面分割线后
搞了几个小时,这个头疼的问题,我给出代码吧。
找到
libcocos2d/platform/winrt/CCFreeTypeFont.cpp
(其中libcocos2d是项目名)然后将其中的函数 addWord 替换为我提供的即可。实在找不到文件的同学直接搜索吧。
需要注意的是我只简单处理了一下,所以中文下只支持UTF8字符串,非UTF8字符串会出问题。当然英文环境下任然是用默认逻辑。
我的cocos2dx版本是 3.2,如果你的版本不是这个,存在个别差异,那就自己改改吧。
希望大家拿走代码的时候在下面评论一下,好提高我分享的积极性,你懂得。
FT_Error CCFreeTypeFont::addWord(const std::string& word)
{
std::vector<TGlyph> glyphs; // glyphs for the word
FT_BBox bbox; // bounding box containing all of the glyphs in the word
int maxWidth = m_inWidth ? m_inWidth : m_windowWidth;
std::string newWord; if(m_currentLine->width > )
{
newWord = ' ' + word;
}
else
{
newWord = word;
} FT_Error error = initWordGlyphs(glyphs, newWord, m_currentLine->pen);
if(!error)
{
compute_bbox(glyphs, &bbox);
/*判断添加进去后整个line是否显示宽度大于设定宽度,是的话进行截取*/
if (Application::getInstance()->getCurrentLanguage() == LanguageType::CHINESE && bbox.xMax > maxWidth)
{
std:size_t start = , end = word.length();
while (true)
{
while (true)//这个字符比最宽还要宽,则进行截取
{
end--;
FT_BBox validBBox = bbox;
std::vector<TGlyph> validGlyphs;
FTLineInfo validLine = FTLineInfo();
validLine.width = ;
validLine.pen.x = ;
validLine.pen.y = ;
//对UTF8字符进行切割
if (end != word.length())
{
while (true)
{
unsigned char utf8charpart = word.at(end - );
if ((utf8charpart & 0x80) != &&
(utf8charpart & 0xe0) != 0xc0 &&
(utf8charpart & 0xf0) != 0xe0 &&
(utf8charpart & 0xf8) != 0xf0)
{
end--;
}
else
{
end--;
break;
}
}
}
std::string validStr = word.substr(start, end - start);
FT_Error validError = initWordGlyphs(validGlyphs, validStr, validLine.pen);
if (validError) break;
compute_bbox(validGlyphs, &validBBox);
if (validBBox.xMax <= maxWidth)
{
m_currentLine->glyphs.insert(validLine.glyphs.end(), validGlyphs.begin(), validGlyphs.end());
if (m_currentLine->width == )
{
m_currentLine->bbox = validBBox;
}
else
{
m_currentLine->bbox.xMax = validBBox.xMax;
}
break;
}
}
start = end;
end = word.length() + ;
if (start == end - ) break;
bbox = FT_BBox();
endLine();
newLine();
}
}
else
{
if (m_currentLine->width == || bbox.xMax <= maxWidth)
{
m_currentLine->glyphs.insert(m_currentLine->glyphs.end(), glyphs.begin(), glyphs.end());
if (m_currentLine->width == )
{
m_currentLine->bbox = bbox;
}
else
{
m_currentLine->bbox.xMax = bbox.xMax;
}
m_currentLine->width = m_currentLine->bbox.xMax - m_currentLine->bbox.xMin;
}
else
{
endLine();
newLine();
addWord(word);
}
}
}
return error;
}
========================================快乐的分割线 ========================================
谢谢 @请让我过好不好 的反馈。我仔细调试后发现造成内存占用过大的原因是中途逐字符计算换行加载成的图像没有释放掉。并且算法是先计算整个字符串长度,然后逐渐从尾部减小一个字符从新计算,当小于最大宽度时候进行换行从新执行上面的计算。这种算法性能很低,因此我改为了从第一个字符开始计算,当算的字符超过一行,则使用上个字符的位置进行换行。
其实还有优化的空间,因为逐字符计算调用的是做事情比较多余的函数,但我没有那么多时间细扣了,下面贴出代码,与分割线之前的版本类似替换系统的 addWord 函数即可:
FT_Error CCFreeTypeFont::addWord(const std::string& word)
{
std::vector<TGlyph> glyphs; // glyphs for the word
FT_BBox bbox; // bounding box containing all of the glyphs in the word
int maxWidth = m_inWidth ? m_inWidth : m_windowWidth;
std::string newWord; if(m_currentLine->width > 0)
{
newWord = ' ' + word;
}
else
{
newWord = word;
} FT_Error error = initWordGlyphs(glyphs, newWord, m_currentLine->pen);
if(!error)
{
compute_bbox(glyphs, &bbox);
/*判断添加进去后整个line是否显示宽度大于设定宽度,是的话进行截取*/
if (Application::getInstance()->getCurrentLanguage() == LanguageType::CHINESE && bbox.xMax > maxWidth)
{
std:size_t start = 0, end = -1, lastValidEnd = 0;
while (true)
{
while (true)//这个字符比最宽还要宽,则进行截取
{
end++;
FT_BBox validBBox = bbox;
std::vector<TGlyph> validGlyphs;
FTLineInfo validLine;
validLine.width = 0;
validLine.pen.x = 0;
validLine.pen.y = 0;
//对UTF8字符进行切割
while (true)
{
end++;
if (end == word.length()) break;
unsigned char utf8charpart = word.at(end);
if (!((utf8charpart & 0x80) != 0 &&
(utf8charpart & 0xe0) != 0xc0 &&
(utf8charpart & 0xf0) != 0xe0 &&
(utf8charpart & 0xf8) != 0xf0))
{
break;
}
} std::string validStr = word.substr(start, end - start);
FT_Error validError = initWordGlyphs(validGlyphs, validStr, validLine.pen);
if (validError) break;
compute_bbox(validGlyphs, &validBBox);
if (validBBox.xMax < maxWidth && end != word.length())
{
lastValidEnd = end;
for (auto glyph = validGlyphs.begin(); glyph != validGlyphs.end(); ++glyph)
{
FT_Done_Glyph(glyph->image);
}
continue;
}
else
{
std::string validStr = word.substr(start, lastValidEnd - start);
lastValidEnd = end;
FT_Error validError = initWordGlyphs(validGlyphs, validStr, validLine.pen);
if (validError) break;
compute_bbox(validGlyphs, &validBBox);
m_currentLine->glyphs.insert(validLine.glyphs.end(), validGlyphs.begin(), validGlyphs.end());
if (m_currentLine->width == 0)
{
m_currentLine->bbox = validBBox;
}
else
{
m_currentLine->bbox.xMax = validBBox.xMax;
}
break;
}
}
start = lastValidEnd;
end = lastValidEnd;
if (end == word.length()) break;
FT_BBox emptybbox;
bbox = emptybbox;
endLine();
newLine();
}
}
else
{
if (m_currentLine->width == 0 || bbox.xMax <= maxWidth)
{
m_currentLine->glyphs.insert(m_currentLine->glyphs.end(), glyphs.begin(), glyphs.end());
if (m_currentLine->width == 0)
{
m_currentLine->bbox = bbox;
}
else
{
m_currentLine->bbox.xMax = bbox.xMax;
}
m_currentLine->width = m_currentLine->bbox.xMax - m_currentLine->bbox.xMin;
}
else
{
endLine();
newLine();
addWord(word);
}
}
}
return error;
}
修复cocos2dx的Label,WP8下不能换行的问题的更多相关文章
- WP8下实现刮刮乐(橡皮擦)功能
说到刮刮乐这个功能,我们最先想到的是上下两张(长方形)重叠,之后对上面这张图片进行操作. 我的想法是:通过手势,让手指划过的地方变成透明的,底部就会显示了. 那如何让图片变为透明呢?这就要对图片的像素 ...
- linux下与windows下的换行符
[原文有些许错误,已作了修改] 回车符号和换行符号产生背景 关于“回车”(carriage return)和“换行”(line feed)这两个概念的来历和区别.在计算机还没有出现之前,有一种叫做电传 ...
- 解决不同操作系统下git换行符一致性问题
一.不同操系统下的换行符CR回车 LF换行Windows/Dos CRLF \r\nLinux/Unix LF \nMacOS CR \r二.解决方法 打卡git bash,设置core.autocr ...
- ie7 下 float换行问题与vertical-align:middle; 失效问题
声明:web小白的笔记,欢迎大神指点!联系QQ:1522025433. ie7 下 float换行问题 请直接看代码中和代码中的注释: <!doctype html> <html&g ...
- cocos2dx 富文本框,支持换行,支持神情(支持汉字截断无乱码)
cocos2dx 富文本框,支持换行,支持表情(支持汉字截断无乱码) 小工在做了一个游戏聊天功能,里面用到插入表情的富文本和换行的问题: 先看效果,不是你要的效果,可return:(截图由于:输入的问 ...
- 转 DOS(CMD)下批处理换行问题/命令行参数换行 arg ms-dos
DOS(CMD)下批处理换行问题本人经常写一些DOS批处理文件,由于批处理中命令的参考较多且长,写在一行太不容易分辨,所以总想找个办法把一条命令分行来写,今天终于试成功两种方法.一.在CMD下,可以用 ...
- Cocos2d-x之Label
| 版权声明:本文为博主原创文章,未经博主允许不得转载. 在游戏开发中经常会使用标签文字,例如,游戏介绍,玩家积分,菜单选项,文字提示等等. LabelTTF 直接支持使用 TTF 字库 ...
- 修复PHP在64位下序列化(serialize)的字符串在32位机器下反序列
32机器下PHP 整型数值的范围最大不超过2147483647,而有些超出范围的数值在64序列化好的数据标识为整型,在反序列时就可能会出错. 尝试使用以下的办法可以修复此问题 function int ...
- zk label控件内容换行
Label控件本身无法换行,不过div却可以,只要设置了div的宽度,那么就想如果在Label控件外套个div会怎样,结果可喜可乐: <div width="80px"> ...
随机推荐
- JS应用实例3:定时弹出广告
在观看视频时候总会发现有广告弹出 这里就做一个类似这样的定时弹出广告的实例: 前面的JS代码和HTML写在同一个文件,实际开发中总是分开来写 用的时候引入即可 HTML代码: <!DOCTYPE ...
- 第五篇: 路由网关(zuul)
在微服务架构中,需要几个基础的服务治理组件,包括服务注册与发现.服务消费.负载均衡.断路器.智能路由.配置管理等,由这几个基础组件相互协作,共同组建了一个简单的微服务系统. 在Spring Cloud ...
- 常用的评价指标:accuracy、precision、recall、F1-score、ROC-AUC、PR-AUC
- Liferay7 BPM门户开发之8: Activiti实用问题集合
1.如何实现审核的上级获取(任务逐级审批) 这个是必备功能,通过Spring的注入+Activiti表达式可以很容易解决. 可参考: http://blog.csdn.net/sunxing007/a ...
- @pathvariable和@RequestParam的区别
@PathVariable 获取的是请求路径url中的值: (http://xxx.xxx.com/get_10.html,侧重于请求的URL路径里面的{xx}变量 ) //获取url中某部分的值 @ ...
- 《JavaScript高级教程》学习笔记一、变量和数据类型
JavaScript的核心语言特性在ECMA-262中是以名为ECMAScript的伪语言的形式来定义的. 一.变量和数据类型 1. 变量 JavaSript是弱类型语言,可以通过var定义任何类型变 ...
- python之有用的3个内置函数(filter/map/reduce)
这三个内置函数还是非常有用的,在工作中用的还不少,顺手,下面一一进行介绍 1.filter 语法:filter(function,iterable) 解释:把迭代器通过function函数进行过滤出想 ...
- Postgresql操作json格式数据
1.select array_to_json('{{1,5},{99,100}}'::int[])
- php 判断客户端是否为手机端访问
function is_mobile_request() { $_SERVER['ALL_HTTP'] = isset($_SERVER['ALL_HTTP'])?$_SERVER['ALL_HTTP ...
- Git 强制回退到某个历史版本再推送到远程
1. 使用 git log 命令历史版本记录回退版本 git reset --hard f6a7c803a6931a9eca011d4e097389e0845cbe49 2. 推送到远程 git pu ...