今天測试发现了游戏的一个问题,系统邮件,假设发了tab,在android上一打开邮件内容就会crash。并且他们非常确定是tab的问题。

凭我多个月的经验(确实没多年。

。)来看。从来没听说在android上会由于一个tab崩溃。并且假设有这个问题。肯定会有非常多人遇到,预计早就吵翻天了,搜索了一下,什么可用信息都没有。

于是写个測试project測试了一下。分别在mac下和windows下,用文本编辑工具编辑了4个txt文档。utf有bom和无bom,内容是“ tab abcd ”,发现都能正常显示,也不会crash。

例如以下:

    unsigned long fSize = 0;
unsigned char *data = CCFileUtils::sharedFileUtils()->getFileData("tab.txt", "rb", &fSize); CCLabelTTF *label = CCLabelTTF::create((const char*)data, "abc", 30);
label->setPosition(ccp(visibleSize.width/2, visibleSize.height/2)); addChild(label);

然后開始怒跟代码,发现project中使用了一个自己定义控件,是为了实现一个富文本框的功能。

所谓富文本框就是能显示各种颜色,能显示url,有的东西还能点的那种。可是这个东西的实现,当中有一步。是把一个utf8字符串拆开,拆成单个字符,把每一个字符的纹理做出来。然后来拼图,拼成一个文本框。那么tab肯定会被拆成单个字符,最后发现就是在生成这个tab的纹理的时候。crash了。堆栈例如以下:

顺便科普一下labelTTF显示的原理,大致就是。通过字体和字号,然后调用对应平台的api。生成一张图(image),注意是一张图啊,然后作为纹理,设置给一个精灵。从上面的堆栈来看,就是在生成这个image的时候crash了。

然后找代码,在CCTexture2D下找到上面堆栈的最后一步。例如以下:

bool CCTexture2D::initWithString(const char *text, const char *fontName, float fontSize, const CCSize& dimensions, CCTextAlignment hAlignment, CCVerticalTextAlignment vAlignment)
{
… … … …
do
{
CCImage* pImage = new CCImage();
CC_BREAK_IF(NULL == pImage);
bRet = pImage->initWithString(text, (int)dimensions.width, (int)dimensions.height, eAlign, fontName, (int)fontSize);
CC_BREAK_IF(!bRet);
bRet = initWithImage(pImage);
CC_SAFE_RELEASE(pImage);
} while (0); … … … …
return bRet;
}

这里第一步是。new一个image出来。然后用文字去init这个image,然后再用这个image去init这个texture。

我们接着看init这个image这里。android下的代码是这种:

bool CCImage::initWithString(
const char * pText,
int nWidth/* = 0*/,
int nHeight/* = 0*/,
ETextAlign eAlignMask/* = kAlignCenter*/,
const char * pFontName/* = nil*/,
int nSize/* = 0*/)
{
bool bRet = false; do
{
CC_BREAK_IF(! pText); BitmapDC &dc = sharedBitmapDC();
CC_BREAK_IF(! dc.getBitmapFromJava(pText, nWidth, nHeight, eAlignMask, pFontName, nSize)); m_pData = dc.m_pData;
CC_BREAK_IF(! m_pData); m_nWidth = (short)dc.m_nWidth;
m_nHeight = (short)dc.m_nHeight;
m_bHasAlpha = true;
m_bPreMulti = true;
m_nBitsPerComponent = 8; bRet = true;
} while (0); return bRet;
}

当中重点是getBitmapFromJava这个函数,例如以下

    bool getBitmapFromJava(const char *text, int nWidth, int nHeight, CCImage::ETextAlign eAlignMask, const char * pFontName, float fontSize)
{
return getBitmapFromJavaShadowStroke( text, nWidth, nHeight, eAlignMask, pFontName, fontSize );
}

从这里就知道了。肯定是把文字。字体。字号这些东西,叫给java层,让它们调用系统相关的东西,返回一个bitmap回来。然后就是下一步,把这个返回的image去初始化texture。可是不须要下一步了。由于到这就crash了。得到例如以下log:

从这个log看,大概意思就是java层在创建bitmap的时候。须要一个图片的宽高。可是这个大小等于0了。

可是之前測试是能够显示tab的,细致想想,之前的測试有一个问题,就是之前的測试都是tab加其它字符的混合,这个地方由于富文本框的处理,是单个tab字符,那么再用单个tab測试一下。果然就和上面一样crash了。

再回到这个crash log本身,这个要生成的图,就是写了字的那个图,那么这个图片的宽高应该取决于字符的内容和字符的大小,怎么会是0呢。难道是由于tab在android上面会被自己主动忽略。

立即再写个project測试:

    unsigned long fSize = 0;
unsigned char *data = CCFileUtils::sharedFileUtils()->getFileData("tab.txt", "rb", &fSize); CCLabelTTF *label = CCLabelTTF::create((const char*)data, "abc", 30);
label->setPosition(ccp(visibleSize.width/2, visibleSize.height/2)); CCLayerColor *col = CCLayerColor::create(ccc4(123, 255,0 , 255));
col->setContentSize(label->getContentSize());
col->ignoreAnchorPointForPosition(false);
col->setAnchorPoint(ccp(0.5, 0.5));
col->setPosition(ccp(label->getPosition().x,label->getPosition().y));
addChild(col); addChild(label);

这个測试和之前那个的差别,主要在于在文字后面加了一个同大小的色块,这样我们就能看到纹理的实际范围(早该如此,事实上是開始2了没想到。。

。),果然发现无论怎样加tab。tab都不会显示,纹理的大小和不加tab的大小是一样的。

假设在cocos2dx上是这样。可是他最后会调用到android系统的java层去生成这个bitmap,说明这个不是cocos2dx的问题,那么在android应用上。tab会不会被忽略呢,果断开个project再測试,例如以下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" > <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world"
android:background="#FFFF0000"/>
</LinearLayout>
<resources>
<string name="app_name">tabTest</string>
<string name="hello_world"> Hello world!</string>
<string name="action_settings">Settings</string>
</resources>

果然还是没显示tab,哈哈哈哈哈,收工~~

总结:android系统会忽略tab,在cocos2dx里面用CCLabelTTF的时候。假设文本内容仅仅有一个tab字符,会crash。

Android 上的 制表符(tab) —— 一个奇妙的字符 (cocos2dx crash)的更多相关文章

  1. Android 上的 制表符(tab) —— 一个奇妙的字符 (二)

    接到上回的说,主要是上回那个问题,我认为是android的bug,黎叔认为是cocos2dx的bug,叫我去提交bug.所以我又继续研究了下. 上回说到会调用java层的函数去创建一个image,然后 ...

  2. Android 上多方式定位元素(python)

    Android 上多方式定位元素(python) 在学习实际UI自动化测试的时候,首先就需要定位元素,然而定位元素也是最头疼的地方,因为元素各种控件名称的缺失会影响元素的准确定位.下面针对Androi ...

  3. PhoneGap 在 Android 上的插件开发方法介绍

    移动应用开发已经成为软件开发的一个重要方向,但是移动开发面临的一个重要问题就是跨平台的问题.PhoneGap 作为一个多平台的软件开发框架,提供了一次编写多个平台的运行.目前已经支持多达 6 个移动平 ...

  4. 警惕rapidxml的陷阱(二):在Android上默认内存池分配数组过大,容易导致栈溢出

    上一篇随笔中提到了,rapidxml在每个xml对象中维护了一个内存池,自己管理变量的生存周期.看起来很好,但我们在实际使用中还是出现了问题. 项目中我们的模块很快写好了,在windows和linux ...

  5. 一个Android上的以滑动揭示的方式显示并切换图片的View

    SlideView是一个Android上的以滑动揭示的方式显示并切换图片的View,以视觉对比的方式把一套相似的图片展示出来. 示例 翻页图片揭示效果: 特性 设置一组(List<ImageIn ...

  6. 准备开发一个运行在Android上的JavaME模拟器

    在一个虚拟机A上运行另外一个虚拟机B看起来是挺不靠谱的一件事,在手机上运行某个虚拟机也不怎么靠谱.并且如果虚拟机A运行在手机上这个听起来就更不靠谱了.但是很多人就在做这样的事.比如在在手机上运行DOS ...

  7. 在Android上山寨了一个Ios9的LivePhotos,放Github上了

    9月10号的凌晨上演了一场IT界的春晚,相信很多果粉(恩,如果你指坚果,那我也没办法了,是在下输了)都熬夜看了吧,看完打算去医院割肾了吧.在发布会上发布了游戏机 Apple TV,更大的砧板 Ipad ...

  8. 使用 Android Studio 开发工具创建一个 Android 应用程序,并在 Genymotion 模拟器上运行

    需求说明: 使用 Android Studio 开发工具创建一个 Android 应用程序,并在 Genymotion 模拟器上运行 实现步骤: 打开 Android Studio,创建一个 Andr ...

  9. Android 上使用 iconfont 的一种便捷方案

    最近在学习 AIOSO(Alibaba Internal Open Source Organization,即阿里巴巴内部开源组织) 的一个子项目MMCherryUI,这是一个流式布局,可以在运行时做 ...

随机推荐

  1. 【UML】UML所扮演的角色(视频总结)

    导读:在国庆中,把UML视频看完了.看完了之后,对于自己到底留下了什么呢,在此就总结一下,前面总结了UML的9种图以及主要的关系,本篇博客,就从整体上对UML做一个说明. 一.总体概述 UML一共讲了 ...

  2. POJ-3352 Road Construction,tarjan缩点求边双连通!

    Road Construction 本来不想做这个题,下午总结的时候发现自己花了一周的时间学连通图却连什么是边双连通不清楚,于是百度了一下相关内容,原来就是一个点到另一个至少有两条不同的路. 题意:给 ...

  3. Java&Android代码规范

    项目中直接导入Square的代码风格文件.(不导入Google的原因是Square同时提供了Java和Android两套统一风格,Google只提供了一套) Square Code Styles Go ...

  4. Linux硬件配置信息

      在网上找了N久,发现了一篇不错的文档,转载一下: 1.查看机器所有硬件信息: dmidecode |more dmesg |more 这2个命令出来的信息都非常多,所以建议后面使用"|m ...

  5. RocketMQ VS kafka

    转自:https://github.com/alibaba/RocketMQ/wiki/rmq_vs_kafka 淘宝内部的交易系统使用了淘宝自主研发的Notify消息中间件,使用MySQL作为消息存 ...

  6. 原 .NET/C# 反射的的性能数据,以及高性能开发建议(反射获取 Attribute 和反射调用方法)

    大家都说反射耗性能,但是到底有多耗性能,哪些反射方法更耗性能:这些问题却没有统一的描述. 本文将用数据说明反射各个方法和替代方法的性能差异,并提供一些反射代码的编写建议.为了解决反射的性能问题,你可以 ...

  7. BZOJ 4650 [Noi2016]优秀的拆分 ——后缀数组

    我们只需要统计在某一个点开始的形如$AA$字符串个数,和结束的个数相乘求和. 首先枚举循环节的长度L.即$\mid (A) \mid=L$ 然后肯定会经过s[i]和[i+L]至少两个点. 然后我们可以 ...

  8. annotation之@Autowired、@Inject、@Resource三者区别

    一.@Autowired 1.@Autowired是spring自带的注解,通过‘AutowiredAnnotationBeanPostProcessor’ 类实现的依赖注入: 2.@Autowire ...

  9. 【(最小权点基)tarjan强连通分量缩点+tarjan模板】HDU 5934 Bomb

    [AC] #include<bits/stdc++.h> using namespace std; typedef long long ll; int n; ; ; const int i ...

  10. weixin-api生成二维码

    二维码长链接转成短链接(减少扫描时间和提高成功率) 微信返回正确的二维码的结果,参数有个url,即二维码图片解析后的地址,也可以根据此URL生成需要的二维码图片,而不需要通过ticket去换取图片了 ...