修复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"> ...
随机推荐
- Testing - 软件测试知识梳理 - 比较质量保证(QA)与质量控制(QC)
QA QC QM 概念 Quality Assurance (质量保证) Quality Control (质量控制) Quality Manage (质量管理) 定义 为达到质量要求所采取的作业技术 ...
- python tricks
1. cities = ['Marseille', 'Amsterdam', 'New York', 'Londom'] # the good way for i, city in enumerate ...
- 课程四(Convolutional Neural Networks),第三 周(Object detection) —— 2.Programming assignments:Car detection with YOLOv2
Autonomous driving - Car detection Welcome to your week 3 programming assignment. You will learn abo ...
- ConfigUtil读取配置文件工具类
ConfigUtil package com.sso.util; import java.io.FileNotFoundException; import java.io.IOException; i ...
- Debug技巧
多线程调试 有些时候为了观察多个线程间变量的不同状态,以及锁的获取等,就会想到在代码里加个断点debug一下. 在IDE里断点停下来的时候,可以切换到另外的线程中,跑其他的代码,不会互相影响.这里是有 ...
- PostgreSQL事务实现
事务简介 事务管理器:有限状态机 日志管理器 CLOG:事务的执行结果 XLOG:undo/redo日志 锁管理器:实现并发控制,读阶段采用MVCC,写阶段采用锁控制实现不同的隔离级别 Postgre ...
- LoadRuner12.53教程(三)
教训1:建立一个Vuser Script jiào教 xùn训 1 : jiàn建 lì立 yī一 gè个 V u s e r S c r ...
- JavaWeb学习 (十七)————JSP属性范围
所谓的属性范围就是一个属性设置之后,可以经过多少个其他页面后仍然可以访问的保存范围. 一.JSP属性范围 JSP中提供了四种属性范围,四种属性范围分别指以下四种: 当前页:一个属性只能在一个页面中取得 ...
- 使用gitlab, jenkins搭建CI(持续集成)系统(3) -- 根据不同触发条件执行不同的构建任务
前面在jenkins中安装的gitlab hook支持不同的参数,具体可以参考gitlab hook文档https://github.com/jenkinsci/gitlab-hook-plugin# ...
- vuex学习及使用
什么是vuex? 在SPA单页面组件的开发中vuex称为状态管理:简单的理解就是你在state中定义了一个数据之后,你可以在所在项目中的任何一个组件里进行获取.进行修改,并且你的修改可以得到全局的响应 ...